diff --git a/.agent/agent.mjs b/.agent/agent.mjs deleted file mode 100644 index 681aaf4458..0000000000 --- a/.agent/agent.mjs +++ /dev/null @@ -1,78 +0,0 @@ -import { spawnSync } from "node:child_process"; -import { readFileSync, existsSync } from "node:fs"; -import { parseArgs } from "node:util"; - -const { positionals, values } = parseArgs({ - allowPositionals: true, - options: { - help: { - type: "boolean", - short: "h", - default: false, - }, - interactive: { - type: "boolean", - short: "i", - default: false, - }, - }, -}); - -if (values.help || positionals.length === 0) { - console.log("Usage: node agent.mjs [extra_args...]"); - console.log("Example: node agent.mjs triage fix bug in authentication"); - console.log("Options:"); - console.log(" -h, --help Show this help message"); - console.log(" -i, --interactive Run in interactive mode"); - process.exit(0); -} - -const promptName = positionals[0].toUpperCase(); -const promptFile = `.agent/${promptName}.md`; -const extraArgs = positionals.slice(1); - -if (!existsSync(promptFile)) { - console.error(`Error: Prompt file "${promptFile}" not found`); - console.error(`Available prompts should be named like: .agent/triage.md, .agent/debug.md, etc.`); - process.exit(1); -} - -try { - let prompt = readFileSync(promptFile, "utf-8"); - - const githubEnvs = Object.entries(process.env) - .filter(([key]) => key.startsWith("GITHUB_")) - .sort(([a], [b]) => a.localeCompare(b)); - - if (githubEnvs.length > 0) { - const githubContext = `## GitHub Environment\n\n${githubEnvs - .map(([key, value]) => `**${key}**: \`${value}\``) - .join("\n")}\n\n---\n\n`; - prompt = githubContext + prompt; - } - - if (extraArgs.length > 0) { - const extraArgsContext = `\n\n## Additional Arguments\n\n${extraArgs.join(" ")}\n\n---\n\n`; - prompt = prompt + extraArgsContext; - } - - const claudeArgs = [prompt, "--allowedTools=Edit,Write,Replace,Search", "--output-format=json"]; - if (!values.interactive) { - claudeArgs.unshift("--print"); - } - - const { status, error } = spawnSync("claude", claudeArgs, { - stdio: "inherit", - encoding: "utf-8", - }); - - if (error) { - console.error("Error running claude:", error); - process.exit(1); - } - - process.exit(status || 0); -} catch (error) { - console.error(`Error reading prompt file "${promptFile}":`, error); - process.exit(1); -} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f8cfaaff8d..b4369fa1a4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,50 +1,3 @@ ### What does this PR do? - - - - -- [ ] Documentation or TypeScript types (it's okay to leave the rest blank in this case) -- [ ] Code changes - ### How did you verify your code works? - - - - - - - - - - - - - - diff --git a/.gitignore b/.gitignore index 186966e5e1..7d8d815f25 100644 --- a/.gitignore +++ b/.gitignore @@ -184,4 +184,6 @@ codegen-for-zig-team.tar.gz *.sock scratch*.{js,ts,tsx,cjs,mjs} -*.bun-build \ No newline at end of file +*.bun-build + +scripts/lldb-inline \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 41736b2877..717cb88fd5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -168,5 +168,5 @@ "WebKit/WebInspectorUI": true, }, "git.detectSubmodules": false, - // "bun.test.customScript": "./build/debug/bun-debug test" + "bun.test.customScript": "./build/debug/bun-debug test" } diff --git a/CLAUDE.md b/CLAUDE.md index 0f6f516a32..c2d03fb20e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This is the Bun repository - an all-in-one JavaScript runtime & toolkit designed - **Build debug version**: `bun bd` - Creates a debug build at `./build/debug/bun-debug` - - Compilation takes ~5 minutes. Don't timeout, be patient. + - **CRITICAL**: DO NOT set a build timeout. Compilation takes ~5 minutes. Be patient. - **Run tests with your debug build**: `bun bd test ` - **CRITICAL**: Never use `bun test` directly - it won't include your changes - **Run any command with debug build**: `bun bd ` @@ -59,8 +59,8 @@ test("my feature", async () => { }); const [stdout, stderr, exitCode] = await Promise.all([ - new Response(proc.stdout).text(), - new Response(proc.stderr).text(), + proc.stdout.text(), + proc.stderr.text(), proc.exited, ]); @@ -69,6 +69,8 @@ test("my feature", async () => { }); ``` +- Always use `port: 0`. Do not hardcode ports. Do not use your own random port number function. + ## Code Architecture ### Language Structure @@ -133,7 +135,6 @@ test("my feature", async () => { When implementing JavaScript classes in C++: 1. Create three classes if there's a public constructor: - - `class Foo : public JSC::JSDestructibleObject` (if has C++ fields) - `class FooPrototype : public JSC::JSNonFinalObject` - `class FooConstructor : public JSC::InternalFunction` @@ -193,7 +194,6 @@ Built-in JavaScript modules use special syntax and are organized as: ``` 3. **Debug helpers**: - - `$debug()` - Like console.log but stripped in release builds - `$assert()` - Assertions stripped in release builds - `if($debug) {}` - Check if debug env var is set @@ -221,15 +221,16 @@ bun ci ## Important Development Notes 1. **Never use `bun test` or `bun ` directly** - always use `bun bd test` or `bun bd `. `bun bd` compiles & runs the debug build. -2. **Use `await using`** for proper resource cleanup with Bun APIs (Bun.spawn, Bun.serve, Bun.connect, etc.) -3. **Follow existing code style** - check neighboring files for patterns -4. **Create regression tests** in `test/regression/issue/` when fixing bugs -5. **Use absolute paths** - Always use absolute paths in file operations -6. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools -7. **Memory management** - In Zig code, be careful with allocators and use defer for cleanup -8. **Cross-platform** - Test on macOS, Linux, and Windows when making platform-specific changes -9. **Debug builds** - Use `BUN_DEBUG_QUIET_LOGS=1` to disable debug logging, or `BUN_DEBUG_=1` to enable specific scopes -10. **Transpiled source** - Find transpiled files in `/tmp/bun-debug-src/` for debugging +2. **All changes must be tested** - if you're not testing your changes, you're not done. +3. **Get your tests to pass**. If you didn't run the tests, your code does not work. +4. **Follow existing code style** - check neighboring files for patterns +5. **Create tests in the right folder** in `test/` and the test must end in `.test.ts` or `.test.tsx` +6. **Use absolute paths** - Always use absolute paths in file operations +7. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools +8. **Memory management** - In Zig code, be careful with allocators and use defer for cleanup +9. **Cross-platform** - Run `bun run zig:check-all` to compile the Zig code on all platforms when making platform-specific changes +10. **Debug builds** - Use `BUN_DEBUG_QUIET_LOGS=1` to disable debug logging, or `BUN_DEBUG_=1` to enable specific scopes +11. **Be humble & honest** - NEVER overstate what you got done or what actually works in commits, PRs or in messages to the user. ## Key APIs and Features diff --git a/bench/snippets/node-zlib-brotli.mjs b/bench/snippets/node-zlib-brotli.mjs index 01208d3ec9..180a173470 100644 --- a/bench/snippets/node-zlib-brotli.mjs +++ b/bench/snippets/node-zlib-brotli.mjs @@ -28,10 +28,4 @@ bench("brotli compress stream", async () => { await pipeline(source, compress); }); -bench("brotli decompress stream", async () => { - const source = Readable.from([compressed]); - const decompress = createBrotliDecompress(); - await pipeline(source, decompress); -}); - await run(); diff --git a/bun.lock b/bun.lock index 85410f2350..d3b8264753 100644 --- a/bun.lock +++ b/bun.lock @@ -15,7 +15,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "source-map-js": "^1.2.0", - "typescript": "^5.7.2", + "typescript": "5.9.2", }, }, "packages/@types/bun": { @@ -32,7 +32,6 @@ }, "devDependencies": { "@types/react": "^19", - "typescript": "^5.0.2", }, "peerDependencies": { "@types/react": "^19", @@ -308,7 +307,7 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], @@ -334,6 +333,8 @@ "@octokit/webhooks/@octokit/webhooks-methods": ["@octokit/webhooks-methods@4.1.0", "", {}, "sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ=="], + "bun-tracestrings/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "camel-case/no-case": ["no-case@2.3.2", "", { "dependencies": { "lower-case": "^1.1.1" } }, "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ=="], "change-case/camel-case": ["camel-case@4.1.2", "", { "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw=="], diff --git a/cmake/Options.cmake b/cmake/Options.cmake index cc27c33a3e..f1f7a59748 100644 --- a/cmake/Options.cmake +++ b/cmake/Options.cmake @@ -102,6 +102,11 @@ else() endif() optionx(ENABLE_ASAN BOOL "If ASAN support should be enabled" DEFAULT ${DEFAULT_ASAN}) +optionx(ENABLE_ZIG_ASAN BOOL "If Zig ASAN support should be enabled" DEFAULT ${ENABLE_ASAN}) + +if (NOT ENABLE_ASAN) + set(ENABLE_ZIG_ASAN OFF) +endif() if(RELEASE AND LINUX AND CI AND NOT ENABLE_ASSERTIONS AND NOT ENABLE_ASAN) set(DEFAULT_LTO ON) diff --git a/cmake/sources/ZigSources.txt b/cmake/sources/ZigSources.txt index 6c3d102112..960b7a2f3b 100644 --- a/cmake/sources/ZigSources.txt +++ b/cmake/sources/ZigSources.txt @@ -10,6 +10,7 @@ src/allocators/NullableAllocator.zig src/analytics.zig src/analytics/schema.zig src/api/schema.zig +src/asan.zig src/ast.zig src/ast/Ast.zig src/ast/ASTMemoryAllocator.zig @@ -377,7 +378,6 @@ src/collections/baby_list.zig src/collections/bit_set.zig src/collections/hive_array.zig src/collections/multi_array_list.zig -src/collections/safety.zig src/compile_target.zig src/comptime_string_map.zig src/copy_file.zig @@ -546,6 +546,7 @@ src/http/AsyncHTTP.zig src/http/CertificateInfo.zig src/http/Decompressor.zig src/http/Encoding.zig +src/http/ETag.zig src/http/FetchRedirect.zig src/http/HeaderBuilder.zig src/http/Headers.zig @@ -633,6 +634,7 @@ src/install/resolvers/folder_resolver.zig src/install/versioned_url.zig src/install/windows-shim/BinLinkingShim.zig src/install/windows-shim/bun_shim_impl.zig +src/install/yarn.zig src/interchange.zig src/interchange/json.zig src/interchange/toml.zig @@ -703,6 +705,9 @@ src/s3/multipart_options.zig src/s3/multipart.zig src/s3/simple_request.zig src/s3/storage_class.zig +src/safety.zig +src/safety/alloc_ptr.zig +src/safety/CriticalSection.zig src/semver.zig src/semver/ExternalString.zig src/semver/SemverObject.zig @@ -853,6 +858,10 @@ src/string/StringJoiner.zig src/string/WTFStringImpl.zig src/sys_uv.zig src/sys.zig +src/sys/coreutils_error_map.zig +src/sys/Error.zig +src/sys/File.zig +src/sys/libuv_error_map.zig src/system_timer.zig src/test/fixtures.zig src/test/recover.zig diff --git a/cmake/targets/BuildBun.cmake b/cmake/targets/BuildBun.cmake index 11bcb62321..43d3b88055 100644 --- a/cmake/targets/BuildBun.cmake +++ b/cmake/targets/BuildBun.cmake @@ -618,7 +618,7 @@ register_command( -Doptimize=${ZIG_OPTIMIZE} -Dcpu=${ZIG_CPU} -Denable_logs=$,true,false> - -Denable_asan=$,true,false> + -Denable_asan=$,true,false> -Dversion=${VERSION} -Dreported_nodejs_version=${NODEJS_VERSION} -Dcanary=${CANARY_REVISION} @@ -1034,7 +1034,6 @@ if(LINUX) --ld-path=${LLD_PROGRAM} -fno-pic -Wl,-no-pie - -Wl,-icf=safe -Wl,--as-needed -Wl,-z,stack-size=12800000 -Wl,--compress-debug-sections=zlib @@ -1060,6 +1059,13 @@ if(LINUX) -Wl,--gc-sections ) endif() + + if (NOT DEBUG AND NOT ENABLE_ASAN) + target_link_options(${bun} PUBLIC + -Wl,-icf=safe + ) + endif() + endif() # --- Symbols list --- diff --git a/cmake/targets/BuildHdrHistogram.cmake b/cmake/targets/BuildHdrHistogram.cmake index bcd4e47c1c..cee0998e7e 100644 --- a/cmake/targets/BuildHdrHistogram.cmake +++ b/cmake/targets/BuildHdrHistogram.cmake @@ -4,7 +4,7 @@ register_repository( REPOSITORY HdrHistogram/HdrHistogram_c COMMIT - 652d51bcc36744fd1a6debfeb1a8a5f58b14022c + 8dcce8f68512fca460b171bccc3a5afce0048779 ) register_cmake_command( diff --git a/cmake/targets/BuildLibArchive.cmake b/cmake/targets/BuildLibArchive.cmake index 9e625ff62f..3a7058683a 100644 --- a/cmake/targets/BuildLibArchive.cmake +++ b/cmake/targets/BuildLibArchive.cmake @@ -4,7 +4,7 @@ register_repository( REPOSITORY libarchive/libarchive COMMIT - 7118f97c26bf0b2f426728b482f86508efc81d02 + 9525f90ca4bd14c7b335e2f8c84a4607b0af6bdf ) register_cmake_command( diff --git a/cmake/targets/BuildMimalloc.cmake b/cmake/targets/BuildMimalloc.cmake index f406d7e36b..91870b66b9 100644 --- a/cmake/targets/BuildMimalloc.cmake +++ b/cmake/targets/BuildMimalloc.cmake @@ -4,7 +4,7 @@ register_repository( REPOSITORY oven-sh/mimalloc COMMIT - 1beadf9651a7bfdec6b5367c380ecc3fe1c40d1a + 178534eeb7c0b4e2f438b513640c6f4d7338416a ) set(MIMALLOC_CMAKE_ARGS @@ -13,14 +13,47 @@ set(MIMALLOC_CMAKE_ARGS -DMI_BUILD_SHARED=OFF -DMI_BUILD_TESTS=OFF -DMI_USE_CXX=ON - -DMI_OVERRIDE=OFF - -DMI_OSX_ZONE=OFF - -DMI_OSX_INTERPOSE=OFF -DMI_SKIP_COLLECT_ON_EXIT=ON + + # ``` + # ❯ mimalloc_allow_large_os_pages=0 BUN_PORT=3004 mem bun http-hello.js + # Started development server: http://localhost:3004 + # + # Peak memory usage: 52 MB + # + # ❯ mimalloc_allow_large_os_pages=1 BUN_PORT=3004 mem bun http-hello.js + # Started development server: http://localhost:3004 + # + # Peak memory usage: 74 MB + # ``` + # + # ``` + # ❯ mimalloc_allow_large_os_pages=1 mem bun --eval 1 + # + # Peak memory usage: 52 MB + # + # ❯ mimalloc_allow_large_os_pages=0 mem bun --eval 1 + # + # Peak memory usage: 30 MB + # ``` + -DMI_NO_THP=1 ) if(ENABLE_ASAN) list(APPEND MIMALLOC_CMAKE_ARGS -DMI_TRACK_ASAN=ON) + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OVERRIDE=OFF) + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OSX_ZONE=OFF) + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OSX_INTERPOSE=OFF) +elseif(APPLE OR LINUX) + # Enable static override when ASAN is not enabled + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OVERRIDE=ON) + if(APPLE) + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OSX_ZONE=ON) + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OSX_INTERPOSE=ON) + else() + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OSX_ZONE=OFF) + list(APPEND MIMALLOC_CMAKE_ARGS -DMI_OSX_INTERPOSE=OFF) + endif() endif() if(DEBUG) @@ -31,13 +64,7 @@ if(ENABLE_VALGRIND) list(APPEND MIMALLOC_CMAKE_ARGS -DMI_VALGRIND=ON) endif() -if(WIN32) - if(DEBUG) - set(MIMALLOC_LIBRARY mimalloc-static-debug) - else() - set(MIMALLOC_LIBRARY mimalloc-static) - endif() -elseif(DEBUG) +if(DEBUG) if (ENABLE_ASAN) set(MIMALLOC_LIBRARY mimalloc-asan-debug) else() @@ -53,6 +80,7 @@ if(APPLE OR (LINUX AND NOT DEBUG)) set(MIMALLOC_LIBRARY CMakeFiles/mimalloc-obj.dir/src/static.c.o) endif() + register_cmake_command( TARGET mimalloc diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index b572088db5..b6c79de049 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -2,7 +2,7 @@ option(WEBKIT_VERSION "The version of WebKit to use") option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading") if(NOT WEBKIT_VERSION) - set(WEBKIT_VERSION 1098cc50652ab1eab171f58f7669e19ca6c276ae) + set(WEBKIT_VERSION 642e2252f6298387edb6d2f991a0408fd0320466) endif() string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX) diff --git a/docs/api/http.md b/docs/api/http.md index e5b052fed9..f3e5b48e55 100644 --- a/docs/api/http.md +++ b/docs/api/http.md @@ -164,6 +164,70 @@ Static responses do not allocate additional memory after initialization. You can Static route responses are cached for the lifetime of the server object. To reload static routes, call `server.reload(options)`. +### File Responses vs Static Responses + +When serving files in routes, there are two distinct behaviors depending on whether you buffer the file content or serve it directly: + +```ts +Bun.serve({ + routes: { + // Static route - content is buffered in memory at startup + "/logo.png": new Response(await Bun.file("./logo.png").bytes()), + + // File route - content is read from filesystem on each request + "/download.zip": new Response(Bun.file("./download.zip")), + }, +}); +``` + +**Static routes** (`new Response(await file.bytes())`) buffer content in memory at startup: + +- **Zero filesystem I/O** during requests - content served entirely from memory +- **ETag support** - Automatically generates and validates ETags for caching +- **If-None-Match** - Returns `304 Not Modified` when client ETag matches +- **No 404 handling** - Missing files cause startup errors, not runtime 404s +- **Memory usage** - Full file content stored in RAM +- **Best for**: Small static assets, API responses, frequently accessed files + +**File routes** (`new Response(Bun.file(path))`) read from filesystem per request: + +- **Filesystem reads** on each request - checks file existence and reads content +- **Built-in 404 handling** - Returns `404 Not Found` if file doesn't exist or becomes inaccessible +- **Last-Modified support** - Uses file modification time for `If-Modified-Since` headers +- **If-Modified-Since** - Returns `304 Not Modified` when file hasn't changed since client's cached version +- **Range request support** - Automatically handles partial content requests with `Content-Range` headers +- **Streaming transfers** - Uses buffered reader with backpressure handling for efficient memory usage +- **Memory efficient** - Only buffers small chunks during transfer, not entire file +- **Best for**: Large files, dynamic content, user uploads, files that change frequently + +### HTTP Caching Behavior + +Both route types implement HTTP caching standards but with different strategies: + +#### Static Routes Caching + +- **ETag generation**: Automatically computes ETag hash from content at startup +- **If-None-Match**: Validates client ETag against server ETag +- **304 responses**: Returns `304 Not Modified` with empty body when ETags match +- **Cache headers**: Inherits any `Cache-Control` headers you provide in the Response +- **Consistency**: ETag remains constant until server restart or route reload + +#### File Routes Caching + +- **Last-Modified**: Uses file's `mtime` for `Last-Modified` header +- **If-Modified-Since**: Compares client date with file modification time +- **304 responses**: Returns `304 Not Modified` when file unchanged since client's cached version +- **Content-Length**: Automatically set based on current file size +- **Dynamic validation**: Checks file modification time on each request + +#### Status Code Handling + +Both route types automatically adjust status codes: + +- **200 → 204**: Empty files (0 bytes) return `204 No Content` instead of `200 OK` +- **200 → 304**: Successful cache validation returns `304 Not Modified` +- **File routes only**: Missing or inaccessible files return `404 Not Found` + ```ts const server = Bun.serve({ static: { diff --git a/docs/api/streams.md b/docs/api/streams.md index 06b6ae72e2..fab5cdedfc 100644 --- a/docs/api/streams.md +++ b/docs/api/streams.md @@ -208,8 +208,8 @@ export class ArrayBufferSink { * * This API might change later to separate Uint8ArraySink and ArrayBufferSink */ - flush(): number | Uint8Array | ArrayBuffer; - end(): ArrayBuffer | Uint8Array; + flush(): number | Uint8Array | ArrayBuffer; + end(): ArrayBuffer | Uint8Array; } ``` diff --git a/docs/cli/test.md b/docs/cli/test.md index 6eda8797d4..bd636bcc39 100644 --- a/docs/cli/test.md +++ b/docs/cli/test.md @@ -158,7 +158,7 @@ See [Test > Lifecycle](https://bun.com/docs/test/lifecycle) for complete documen ## Mocks -Create mock functions with the `mock` function. Mocks are automatically reset between tests. +Create mock functions with the `mock` function. ```ts import { test, expect, mock } from "bun:test"; diff --git a/docs/guides/util/detect-bun.md b/docs/guides/util/detect-bun.md index 0a2506b5c3..03a40358c2 100644 --- a/docs/guides/util/detect-bun.md +++ b/docs/guides/util/detect-bun.md @@ -14,7 +14,7 @@ if (typeof Bun !== "undefined") { --- -In TypeScript environments, the previous approach will result in a type error unless `bun-types` is globally installed. To avoid this, you can check `process.versions` instead. +In TypeScript environments, the previous approach will result in a type error unless `@types/bun` is installed. To avoid this, you can check `process.versions` instead. ```ts if (process.versions.bun) { diff --git a/docs/runtime/nodejs-apis.md b/docs/runtime/nodejs-apis.md index f9a9622994..1e19fa90fb 100644 --- a/docs/runtime/nodejs-apis.md +++ b/docs/runtime/nodejs-apis.md @@ -148,7 +148,7 @@ This page is updated regularly to reflect compatibility status of the latest ver ### [`node:vm`](https://nodejs.org/api/vm.html) -🟡 Core functionality works, but experimental VM ES modules are not implemented, including `vm.Module`, `vm.SourceTextModule`, `vm.SyntheticModule`,`importModuleDynamically`, and `vm.measureMemory`. Options like `timeout`, `breakOnSigint`, `cachedData` are not implemented yet. +🟡 Core functionality and ES modules are implemented, including `vm.Script`, `vm.createContext`, `vm.runInContext`, `vm.runInNewContext`, `vm.runInThisContext`, `vm.compileFunction`, `vm.isContext`, `vm.Module`, `vm.SourceTextModule`, `vm.SyntheticModule`, and `importModuleDynamically` support. Options like `timeout` and `breakOnSigint` are fully supported. Missing `vm.measureMemory` and some `cachedData` functionality. ### [`node:wasi`](https://nodejs.org/api/wasi.html) @@ -214,6 +214,10 @@ The table below lists all globals implemented by Node.js and Bun's current compa 🟢 Fully implemented. +### [`Atomics`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics) + +🟢 Fully implemented. + ### [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) 🟢 Fully implemented. diff --git a/docs/test/writing.md b/docs/test/writing.md index 6ecb625de2..f61e911426 100644 --- a/docs/test/writing.md +++ b/docs/test/writing.md @@ -426,6 +426,54 @@ test("exactly two assertions", () => { This helps ensure all your assertions run, especially in complex async code with multiple code paths. +## Type Testing + +Bun includes `expectTypeOf` for testing typescript types, compatible with Vitest. + +### expectTypeOf + +{% callout %} + +**Note** — These functions are no-ops at runtime - you need to run TypeScript separately to verify the type checks. + +{% endcallout %} + +The `expectTypeOf` function provides type-level assertions that are checked by TypeScript's type checker. **Important**: + +To test your types: + +1. Write your type assertions using `expectTypeOf` +2. Run `bunx tsc --noEmit` to check that your types are correct + +```ts +import { expectTypeOf } from "bun:test"; + +// Basic type assertions +expectTypeOf().toEqualTypeOf(); +expectTypeOf(123).toBeNumber(); +expectTypeOf("hello").toBeString(); + +// Object type matching +expectTypeOf({ a: 1, b: "hello" }).toMatchObjectType<{ a: number }>(); + +// Function types +function greet(name: string): string { + return `Hello ${name}`; +} + +expectTypeOf(greet).toBeFunction(); +expectTypeOf(greet).parameters.toEqualTypeOf<[string]>(); +expectTypeOf(greet).returns.toEqualTypeOf(); + +// Array types +expectTypeOf([1, 2, 3]).items.toBeNumber(); + +// Promise types +expectTypeOf(Promise.resolve(42)).resolves.toBeNumber(); +``` + +For full documentation on expectTypeOf matchers, see the [API Reference](/reference/bun/test/expectTypeOf) + ## Matchers Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress [here](https://github.com/oven-sh/bun/issues/1825). @@ -629,17 +677,17 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap --- -- ❌ +- ✅ - [`.toHaveReturnedWith()`](https://jestjs.io/docs/expect#tohavereturnedwithvalue) --- -- ❌ +- ✅ - [`.toHaveLastReturnedWith()`](https://jestjs.io/docs/expect#tohavelastreturnedwithvalue) --- -- ❌ +- ✅ - [`.toHaveNthReturnedWith()`](https://jestjs.io/docs/expect#tohaventhreturnedwithnthcall-value) --- diff --git a/examples/.gitignore b/examples/.gitignore deleted file mode 100644 index 38f8778e42..0000000000 --- a/examples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bun-examples-all \ No newline at end of file diff --git a/examples/.is-examples-folder b/examples/.is-examples-folder deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/examples/add.rs b/examples/add.rs deleted file mode 100644 index ad01074d1d..0000000000 --- a/examples/add.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[no_mangle] -pub extern "C" fn add(a: i32, b: i32) -> i32 { - a + b -} - -// to compile: -// rustc --crate-type cdylib add.rs diff --git a/examples/add.ts b/examples/add.ts deleted file mode 100644 index e975b122e0..0000000000 --- a/examples/add.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { dlopen, suffix } from "bun:ffi"; - -const { - symbols: { add }, -} = dlopen(`./libadd.${suffix}`, { - add: { - args: ["i32", "i32"], - returns: "i32", - }, -}); - -console.log(add(1, 2)); diff --git a/examples/add.zig b/examples/add.zig deleted file mode 100644 index 24b78bec74..0000000000 --- a/examples/add.zig +++ /dev/null @@ -1,6 +0,0 @@ -pub export fn add(a: i32, b: i32) i32 { - return a + b; -} - -// to compile: -// zig build-lib -OReleaseFast ./add.zig -dynamic --name add diff --git a/examples/bun-hot-websockets.js b/examples/bun-hot-websockets.js deleted file mode 100644 index 88a01bcd46..0000000000 --- a/examples/bun-hot-websockets.js +++ /dev/null @@ -1,89 +0,0 @@ -// To run this example: -// -// bun --hot bun-hot-websockets.js -// - -const css = ([inner]) => { - return inner; -}; - -const styles = css` - #bun { - margin: 0 auto; - margin-top: 200px; - object-fit: cover; - } - html, - body { - margin: 0; - padding: 0; - } - body { - background: #f1239f; - font-family: "Inter", sans-serif; - display: flex; - align-items: center; - justify-content: center; - align-content: center; - color: white; - } - h1 { - padding: 0; - text-align: center; - font-size: 3rem; - -webkit-text-stroke: 2px black; - } - * { - box-sizing: border-box; - } -`; - -Bun.serve({ - websocket: { - message(ws, msg) { - ws.send(styles); - }, - }, - fetch(req, server) { - if (req.url.endsWith("/hot")) { - if (server.upgrade(req)) - return new Response("", { - status: 101, - }); - } - - return new Response( - ` - - - - - WebSockets - - - - -
- Bun -

bun --hot websockets

-
- - - `, - { - headers: { - "Content-Type": "text/html; charset=utf-8", - }, - }, - ); - }, -}); diff --git a/examples/cat.ts b/examples/cat.ts deleted file mode 100644 index 0634daaf19..0000000000 --- a/examples/cat.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { resolve } from "path"; -const { write, stdout, file } = Bun; -import { argv } from "process"; - -const path = resolve(argv.at(-1)!); -await write(stdout, file(path)); - -Bun.stdout; -process.stdout; diff --git a/examples/change-array-by-copy.js b/examples/change-array-by-copy.js deleted file mode 100644 index 78cf6f3de3..0000000000 --- a/examples/change-array-by-copy.js +++ /dev/null @@ -1,11 +0,0 @@ -const sequence = [1, 2, 3]; -sequence.toReversed(); // => [3, 2, 1] -sequence; // => [1, 2, 3] - -const outOfOrder = new Uint8Array([3, 1, 2]); -outOfOrder.toSorted(); // => Uint8Array [1, 2, 3] -outOfOrder; // => Uint8Array [3, 1, 2] - -const correctionNeeded = [1, 1, 3]; -correctionNeeded.with(1, 2); // => [1, 2, 3] -correctionNeeded; // => [1, 1, 3] diff --git a/examples/hashing.js b/examples/hashing.js deleted file mode 100644 index 7a66b9fefe..0000000000 --- a/examples/hashing.js +++ /dev/null @@ -1,23 +0,0 @@ -// Accepts a string, TypedArray, or Blob (file blob support is not implemented but planned) -const input = "hello world".repeat(400); - -// Bun.hash() defaults to Wyhash because it's fast -console.log(Bun.hash(input)); - -console.log(Bun.hash.wyhash(input)); -// and returns a bigint -// all of these hashing functions return number if 32-bit or bigint if 64-bit, not typed arrays. -console.log(Bun.hash.adler32(input)); // number -console.log(Bun.hash.crc32(input)); // number -console.log(Bun.hash.cityHash32(input)); // number -console.log(Bun.hash.cityHash64(input)); // bigint -console.log(Bun.hash.xxHash32(input)); // number -console.log(Bun.hash.xxHash64(input)); // bigint -console.log(Bun.hash.xxHash3(input)); // bigint -console.log(Bun.hash.murmur32v3(input)); // number -console.log(Bun.hash.murmur32v2(input)); // number -console.log(Bun.hash.murmur64v2(input)); // bigint -console.log(Bun.hash.rapidhash(input)); // bigint - -// Second argument accepts a seed where relevant -console.log(Bun.hash(input, 12345)); diff --git a/examples/html-rewriter.ts b/examples/html-rewriter.ts deleted file mode 100644 index 3017350e73..0000000000 --- a/examples/html-rewriter.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Start a fast HTTP server from a function - -Bun.serve({ - async fetch(req) { - const { pathname } = new URL(req.url); - if (!(pathname.startsWith("/https://") || pathname.startsWith("/http://"))) { - return new Response("Enter a path that starts with https:// or http://\n", { - status: 400, - }); - } - - const response = await fetch(req.url.substring("http://localhost:3000/".length), req.clone()); - - return new HTMLRewriter() - .on("a[href]", { - element(element) { - element.setAttribute("href", "https://www.youtube.com/watch?v=dQw4w9WgXcQ"); - }, - }) - .transform(response); - }, - - // this is called when fetch() throws or rejects - // error(err: Error) { - // }, - - // this boolean enables the bun's default error handler - // sometime after the initial release, it will auto reload as well - development: process.env.NODE_ENV !== "production", - // note: this isn't node, but for compatibility bun supports process.env + more stuff in process - - // SSL is enabled if these two are set - // certFile: './cert.pem', - // keyFile: './key.pem', - - port: 3000, // number or string -}); diff --git a/examples/http-file-extended.ts b/examples/http-file-extended.ts deleted file mode 100644 index 14886af5ea..0000000000 --- a/examples/http-file-extended.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { file, serve } from "bun"; -import { existsSync, statSync } from "fs"; - -serve({ - fetch(req: Request) { - let pathname = new URL(req.url).pathname.substring(1); - if (pathname == "") { - pathname = import.meta.url.replace("file://", ""); - } - - if (!existsSync(pathname)) { - return new Response(null, { status: 404 }); - } - - const stats = statSync(pathname); - - // https://github.com/gornostay25/svelte-adapter-bun/blob/master/src/sirv.js - const headers = new Headers({ - "Content-Length": "" + stats.size, - "Last-Modified": stats.mtime.toUTCString(), - ETag: `W/"${stats.size}-${stats.mtime.getTime()}"`, - }); - - if (req.headers.get("if-none-match") === headers.get("ETag")) { - return new Response(null, { status: 304 }); - } - - const opts = { code: 200, start: 0, end: Infinity, range: false }; - - if (req.headers.has("range")) { - opts.code = 206; - let [x, y] = req.headers.get("range")!.replace("bytes=", "").split("-"); - let end = (opts.end = parseInt(y, 10) || stats.size - 1); - let start = (opts.start = parseInt(x, 10) || 0); - - if (start >= stats.size || end >= stats.size) { - headers.set("Content-Range", `bytes */${stats.size}`); - return new Response(null, { - headers: headers, - status: 416, - }); - } - - headers.set("Content-Range", `bytes ${start}-${end}/${stats.size}`); - headers.set("Content-Length", "" + (end - start + 1)); - headers.set("Accept-Ranges", "bytes"); - opts.range = true; - } - - if (opts.range) { - return new Response(file(pathname).slice(opts.start, opts.end), { - headers, - status: opts.code, - }); - } - - return new Response(file(pathname), { headers, status: opts.code }); - }, - - // this is called when fetch() throws or rejects - // error(err: Error) { - // return new Response("uh oh! :(" + String(err.toString()), { status: 500 }); - // }, - - // this boolean enables the bun's default error handler - // sometime after the initial release, it will auto reload as well - development: process.env.NODE_ENV !== "production", - // note: this isn't node, but for compatibility bun supports process.env + more stuff in process - - // SSL is enabled if these two are set - // certFile: './cert.pem', - // keyFile: './key.pem', - - port: 3000, // number or string - hostname: "localhost", // defaults to 0.0.0.0 -}); diff --git a/examples/http-file.ts b/examples/http-file.ts deleted file mode 100644 index bcd28227c6..0000000000 --- a/examples/http-file.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { file, serve } from "bun"; - -serve({ - fetch(req: Request) { - const pathname = new URL(req.url).pathname.substring(1); - - // If the URL is empty, display this file. - if (pathname === "") { - return new Response(file(import.meta.url.replace("file://", ""))); - } - - return new Response(file(pathname)); - }, - - // this is called when fetch() throws or rejects - // error(err: Error) { - // return new Response("uh oh! :(" + String(err.toString()), { status: 500 }); - // }, - - // this boolean enables the bun's default error handler - // sometime after the initial release, it will auto reload as well - development: process.env.NODE_ENV !== "production", - // note: this isn't node, but for compatibility bun supports process.env + more stuff in process - - // SSL is enabled if these two are set - // certFile: './cert.pem', - // keyFile: './key.pem', - - port: 3000, // number or string - hostname: "localhost", // defaults to 0.0.0.0 -}); diff --git a/examples/http-request-body.ts b/examples/http-request-body.ts deleted file mode 100644 index b9a4548896..0000000000 --- a/examples/http-request-body.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { serve } from "bun"; - -serve({ - async fetch(req) { - // body is a ReadableStream - const body = req.body; - - const writer = Bun.file(`upload.${Date.now()}.txt`).writer(); - for await (const chunk of body!) { - writer.write(chunk); - } - const wrote = await writer.end(); - - // @ts-ignore - return Response.json({ wrote, type: req.headers.get("Content-Type") }); - }, -}); diff --git a/examples/http-stop.ts b/examples/http-stop.ts deleted file mode 100644 index a9ee908926..0000000000 --- a/examples/http-stop.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { serve } from "bun"; - -const server = serve({ - fetch(req) { - return new Response(`Pending requests count: ${this.pendingRequests}`); - }, -}); - -// Stop the server after 5 seconds -setTimeout(() => { - server.stop(); -}, 5000); diff --git a/examples/http.ts b/examples/http.ts deleted file mode 100644 index 8b17c320cc..0000000000 --- a/examples/http.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Start a fast HTTP server from a function -Bun.serve({ - fetch(req: Request) { - return new Response(`Echo: ${req.url}`); - }, - - // baseURI: "http://localhost:3000", - - // this is called when fetch() throws or rejects - // error(err: Error) { - // return new Response("uh oh! :(\n" + err.toString(), { status: 500 }); - // }, - - // this boolean enables bun's default error handler - development: process.env.NODE_ENV !== "production", - // note: this isn't node, but for compatibility bun supports process.env + more stuff in process - - // SSL is enabled if these two are set - // certFile: './cert.pem', - // keyFile: './key.pem', - - port: 3000, // number or string -}); -// Start a fast HTTP server from the main file's export -// export default { -// fetch(req) { -// return new Response( -// `This is another way to start a server! -// if the main file export default's an object -// with 'fetch'. Bun automatically calls Bun.serve` -// ); -// }, -// // so autocomplete & type checking works -// } as Bun.Serve; diff --git a/examples/lambda.ts b/examples/lambda.ts deleted file mode 100644 index ec4817817b..0000000000 --- a/examples/lambda.ts +++ /dev/null @@ -1,193 +0,0 @@ -const { AWS_LAMBDA_RUNTIME_API, LAMBDA_TASK_ROOT, _HANDLER } = process.env; - -if (!AWS_LAMBDA_RUNTIME_API || AWS_LAMBDA_RUNTIME_API === "") { - throw new Error("AWS_LAMBDA_RUNTIME_API is not set"); -} - -const nextURL = `http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next`; -const sourceDir = LAMBDA_TASK_ROOT; -if (!sourceDir) { - throw new Error("handler is not set"); -} -if (!_HANDLER) { - throw new Error("handler is not set"); -} - -// don't care if this fails -if (process.cwd() !== sourceDir) { - try { - process.chdir(sourceDir); - } catch (e) {} -} - -var handlerDot = _HANDLER.lastIndexOf("."); -var sourcefile = handlerDot > 0 ? _HANDLER.substring(0, handlerDot) : _HANDLER; -if (sourcefile.length === 0) { - throw new Error("handler is not set"); -} -if (!sourcefile.startsWith("/")) { - sourcefile = `./${sourcefile}`; -} -function noop() {} -const method = (handlerDot > 0 ? _HANDLER.substring(handlerDot) : "") || "GET"; - -if (typeof process.env.VERBOSE !== "undefined") { - console.time(`Loaded ${sourcefile}`); -} -var Handler; - -try { - Handler = await import(sourcefile); -} catch (e: any) { - console.error("Error loading sourcefile:", e); - try { - await fetch(new URL(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/init/error`).href, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - errorMessage: e.message, - errorType: e.name, - stackTrace: e?.stack?.split("\n") ?? [], - }), - }); - } catch (e2) { - console.error("Error sending error to runtime:", e2); - } - process.exit(1); -} - -if (typeof process.env.VERBOSE !== "undefined") { - console.timeEnd(`Loaded ${sourcefile}`); -} - -const handlerFunction = Handler.default?.fetch; -if (typeof handlerFunction !== "function") { - const e = new Error(`${sourcefile} must export default a function called fetch - -Here is an example: - -export default { - fetch(req) { - return new Response("Hello World"); - } -} -`); - - console.error(e); - - try { - await fetch(new URL(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/init/error`).href, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - errorMessage: e.message, - errorType: e.name, - stackTrace: e?.stack?.split("\n") ?? [], - }), - }); - } catch (e2) { - console.error("Error sending error to runtime:", e2); - } - - process.exit(1); -} - -var baseURLString = AWS_LAMBDA_RUNTIME_API; -if ("baseURI" in Handler.default) { - baseURLString = Handler.default.baseURI?.toString(); -} - -var baseURL; -try { - baseURL = new URL(baseURLString); -} catch (e: any) { - console.error("Error parsing baseURI:", e); - try { - await fetch(new URL(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/init/error`).href, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - errorMessage: e.message, - errorType: e.name, - stackTrace: e?.stack?.split("\n") || [], - }), - }); - } catch (e2) { - console.error("Error sending error to runtime:", e2); - } - - process.exit(1); -} - -async function runHandler(response: Response) { - const traceID = response.headers.get("Lambda-Runtime-Trace-Id"); - const requestID = response.headers.get("Lambda-Runtime-Aws-Request-Id"); - var request = new Request(baseURL.href, { - method, - headers: response.headers, - body: parseInt(response.headers.get("Content-Length") || "0", 10) > 0 ? await response.blob() : undefined, - }); - // we are done with the Response object here - // allow it to be GC'd - (response as any) = undefined; - - var result: Response; - try { - if (typeof process.env.VERBOSE !== "undefined") { - console.time(`[${traceID}] Run ${request.url}`); - } - result = handlerFunction(request, {}); - if (result && (result as any).then) { - await result; - } - } catch (e1: any) { - if (typeof process.env.VERBOSE !== "undefined") { - console.error(`[${traceID}] Error running handler:`, e1); - } - fetch(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestID}/error`, { - method: "POST", - - body: JSON.stringify({ - errorMessage: e1.message, - errorType: e1.name, - stackTrace: e1?.stack?.split("\n") ?? [], - }), - }).finally(noop); - return; - } finally { - if (typeof process.env.VERBOSE !== "undefined") { - console.timeEnd(`[${traceID}] Run ${request.url}`); - } - } - - if (!result || !("headers" in result)) { - await fetch(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestID}/error`, { - method: "POST", - body: JSON.stringify({ - errorMessage: "Expected Response object", - errorType: "ExpectedResponseObject", - stackTrace: [], - }), - }); - return; - } - - await fetch(`http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${requestID}/response`, { - method: "POST", - headers: result.headers, - body: await result.blob(), - }); - (result as any) = undefined; -} - -while (true) { - fetch(nextURL).then(runHandler, console.error); -} - -export {}; diff --git a/examples/macros/bun.lock b/examples/macros/bun.lock deleted file mode 100644 index 9098490d13..0000000000 --- a/examples/macros/bun.lock +++ /dev/null @@ -1,48 +0,0 @@ -{ - "lockfileVersion": 1, - "workspaces": { - "": { - "name": "macros", - "dependencies": { - "moment": "^2.29.1", - "papaparse": "^5.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-refresh": "^0.10.0", - }, - "devDependencies": { - "@types/react": "^17.0.24", - "@types/react-dom": "^17.0.9", - }, - }, - }, - "packages": { - "@types/prop-types": ["@types/prop-types@15.7.5", "", {}, "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="], - - "@types/react": ["@types/react@17.0.53", "", { "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, "sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw=="], - - "@types/react-dom": ["@types/react-dom@17.0.19", "", { "dependencies": { "@types/react": "^17" } }, "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ=="], - - "@types/scheduler": ["@types/scheduler@0.16.2", "", {}, "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="], - - "csstype": ["csstype@3.1.1", "", {}, "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - - "moment": ["moment@2.29.4", "", {}, "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="], - - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "papaparse": ["papaparse@5.3.2", "", {}, "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw=="], - - "react": ["react@17.0.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="], - - "react-dom": ["react-dom@17.0.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "scheduler": "^0.20.2" }, "peerDependencies": { "react": "17.0.2" } }, "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA=="], - - "react-refresh": ["react-refresh@0.10.0", "", {}, "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ=="], - - "scheduler": ["scheduler@0.20.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ=="], - } -} diff --git a/examples/macros/components/covid19.tsx b/examples/macros/components/covid19.tsx deleted file mode 100644 index 16877b5cef..0000000000 --- a/examples/macros/components/covid19.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { fetchCSV } from "macro:fetchCSV"; - -export const Covid19 = () => { - const rows = fetchCSV("https://covid19.who.int/WHO-COVID-19-global-data.csv", { - last: 100, - columns: ["New_cases", "Date_reported", "Country"], - }); - - return ( -
-

Covid-19

-
last {rows.length} updates from the WHO
-
-
-
New Cases
-
Date
-
Country
-
- - {rows.map((row, index) => ( -
-
{row[0]}
-
{row[1]}
-
{row[2]}
-
- ))} -
-
- ); -}; diff --git a/examples/macros/components/example.jsx b/examples/macros/components/example.jsx deleted file mode 100644 index 6f2760b76a..0000000000 --- a/examples/macros/components/example.jsx +++ /dev/null @@ -1,15 +0,0 @@ -// source code -import { matchInFile } from "macro:matchInFile"; - -export const IPAddresses = () => ( -
-

recent ip addresses

-
- {matchInFile("access.log", /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}/).map((ipAddress, index) => ( -
- {ipAddress} -
- ))} -
-
-); diff --git a/examples/macros/components/index.tsx b/examples/macros/components/index.tsx deleted file mode 100644 index f5d0ffe0f8..0000000000 --- a/examples/macros/components/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as ReactDOM from "react-dom"; -import * as React from "react"; -import { IPAddresses } from "./example"; -import { Covid19 } from "./covid19"; - -const Start = function () { - const root = document.createElement("div"); - document.body.appendChild(root); - - // comment out to switch between examples - // ReactDOM.render(, root); - ReactDOM.render(, root); -}; - -Start(); diff --git a/examples/macros/example.js b/examples/macros/example.js deleted file mode 100644 index d612c1fa43..0000000000 --- a/examples/macros/example.js +++ /dev/null @@ -1,4 +0,0 @@ -// source code -import { mysteryBox } from "macro:./mystery-box"; - -export default "You roll! " + mysteryBox(123); diff --git a/examples/macros/fetchCSV.tsx b/examples/macros/fetchCSV.tsx deleted file mode 100644 index 55a12bc424..0000000000 --- a/examples/macros/fetchCSV.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import Pappa from "papaparse"; -// Example usage: -// const rows = fetchCSV( -// "https://covid19.who.int/WHO-COVID-19-global-data.csv", -// { -// last: 100, -// columns: ["New_cases", "Date_reported", "Country"], -// } -// ); -export async function fetchCSV(callExpression) { - console.time("fetchCSV Total"); - const [ - urlNode, - { - properties: { last: limit = 10, columns = [] }, - }, - ] = callExpression.arguments; - const url = urlNode.get(); - - console.time("Fetch"); - const response = await fetch(url); - const csvText = await response.text(); - console.timeEnd("Fetch"); - - console.time("Parse"); - let rows = Pappa.parse(csvText, { fastMode: true }).data; - console.timeEnd("Parse"); - - console.time("Render"); - const columnIndices = new Array(columns.length); - - for (let i = 0; i < columns.length; i++) { - columnIndices[i] = rows[0].indexOf(columns[i]); - } - - rows = rows - .slice(Math.max(limit, rows.length) - limit) - .reverse() - .filter(columns => columns.every(Boolean)); - const value = ( - - {rows.map(columns => ( - - {columnIndices.map(columnIndex => ( - - ))} - - ))} - - ); - console.timeEnd("Render"); - console.timeEnd("fetchCSV Total"); - return value; -} diff --git a/examples/macros/matchInFile.tsx b/examples/macros/matchInFile.tsx deleted file mode 100644 index 4793661d99..0000000000 --- a/examples/macros/matchInFile.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// macro code -export async function matchInFile(callExpression: BunAST.CallExpression) { - const [filePathNode, matcherNode] = callExpression.arguments; - let filePath: string; - filePath = filePathNode.get(); - - let matcher: RegExp; - matcher = matcherNode.get(); - const file: string = await Bun.file(Bun.cwd + filePath).text(); - - return ( - - {file - .split("\n") - .map(line => line.match(matcher)) - .filter(Boolean) - .reverse() - .map(line => ( - - ))} - - ); -} diff --git a/examples/macros/mystery-box.ts b/examples/macros/mystery-box.ts deleted file mode 100644 index c686f82c39..0000000000 --- a/examples/macros/mystery-box.ts +++ /dev/null @@ -1,13 +0,0 @@ -export function mysteryBox(callExpression) { - console.log(callExpression.log); - // get arguments - const [countNode] = callExpression.arguments; - const countString: string = countNode.get(); - const count: number = parseInt(countString, 10); - - // validate - if (!(count >= 1 && count <= 1000)) return new Error(`Argument ${countString} is expected to be between 1 and 1000`); - - // return a value - return (Math.random() * count) | 0; -} diff --git a/examples/macros/now.tsx b/examples/macros/now.tsx deleted file mode 100644 index d5a9e79122..0000000000 --- a/examples/macros/now.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import moment from "moment"; -export function now(node) { - var fmt = "HH:mm:ss"; - const args = node.arguments; - if (args[0] instanceof ) { - fmt = args[0].get(); - } - const time = moment().format(fmt); - return ; -} diff --git a/examples/macros/package.json b/examples/macros/package.json deleted file mode 100644 index dff2c648e1..0000000000 --- a/examples/macros/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "macros", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "dependencies": { - "moment": "^2.29.1", - "papaparse": "^5.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-refresh": "^0.10.0" - }, - "devDependencies": { - "@types/react": "^17.0.24", - "@types/react-dom": "^17.0.9" - } -} diff --git a/examples/macros/public/index.html b/examples/macros/public/index.html deleted file mode 100644 index dff19b990a..0000000000 --- a/examples/macros/public/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - Macro test - - - - - - - - - - diff --git a/examples/macros/styles.css b/examples/macros/styles.css deleted file mode 100644 index a8109a8206..0000000000 --- a/examples/macros/styles.css +++ /dev/null @@ -1,47 +0,0 @@ -html { - font-size: 4rem; - margin: 0; - padding: 0; - background-color: black; - - color: rgb(0, 255, 0); - font-family: "Courier"; -} - -body { - margin: 48px auto; - text-align: center; -} - -.Line { - font-size: 0.5rem; - font-family: monospace; -} - -.Table { - display: grid; - width: fit-content; -} - -.Row, -.Header { - display: grid; - grid-template-columns: 2fr 1fr 1fr; - text-align: right; - - column-gap: 2rem; -} - -.Heading { - text-align: right; -} - -.Header { - border-bottom: 1px solid rgb(0, 255, 0); - margin-bottom: 20px; - padding-bottom: 20px; -} - -.Heading:nth-of-type(2) { - text-align: left; -} diff --git a/examples/macros/tsconfig.json b/examples/macros/tsconfig.json deleted file mode 100644 index 4a98f5cad0..0000000000 --- a/examples/macros/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": {}, - "jsx": "preserve" - } -} diff --git a/examples/mmap/1.js b/examples/mmap/1.js deleted file mode 100644 index 75018cb963..0000000000 --- a/examples/mmap/1.js +++ /dev/null @@ -1,11 +0,0 @@ -const map = Bun.mmap("./mmap.txt", { shared: true }); -const utf8decoder = new TextDecoder("utf-8"); - -let old = new TextEncoder().encode("12345"); - -setInterval(() => { - old = old.sort((a, b) => (Math.random() > 0.5 ? -1 : 1)); - console.log(`changing mmap to ~> ${utf8decoder.decode(old)}`); - - map.set(old); -}, 4); diff --git a/examples/mmap/2.js b/examples/mmap/2.js deleted file mode 100644 index c4b68bd9a9..0000000000 --- a/examples/mmap/2.js +++ /dev/null @@ -1,22 +0,0 @@ -const map = Bun.mmap("./mmap.txt"); - -function buffer_hash(buffer) { - let hash = 0; - for (let i = 0; i < buffer.length; i++) { - hash = (hash << 5) - hash + buffer[i]; - hash |= 0; // Convert to 32bit integer - } - return hash; -} - -const decoder = new TextDecoder(); - -let hash = buffer_hash(map); -console.log(decoder.decode(map)); - -while (true) { - if (buffer_hash(map) !== hash) { - hash = buffer_hash(map); - console.log(`mmap changed to ~> ${decoder.decode(map)}`); - } -} diff --git a/examples/mmap/mmap.txt b/examples/mmap/mmap.txt deleted file mode 100644 index 6931040dd4..0000000000 --- a/examples/mmap/mmap.txt +++ /dev/null @@ -1 +0,0 @@ -43521 \ No newline at end of file diff --git a/examples/openInEditor.js b/examples/openInEditor.js deleted file mode 100644 index 30992d9589..0000000000 --- a/examples/openInEditor.js +++ /dev/null @@ -1,23 +0,0 @@ -import { resolve } from "path"; -import { parse } from "querystring"; - -export default { - fetch(req) { - const url = new URL(req.url); - if (url.pathname === "/favicon.ico") return new Response("nooo dont open favicon in editor", { status: 404 }); - - var pathname = req.url.substring(1); - const q = pathname.indexOf("?"); - var { editor } = parse(pathname.substring(q + 1)) || {}; - - if (q > 0) { - pathname = pathname.substring(0, q); - } - - Bun.openInEditor(resolve(pathname), { - editor, - }); - - return new Response(`Opened ${req.url}`); - }, -}; diff --git a/examples/react-fast-refresh-test/bun.lock b/examples/react-fast-refresh-test/bun.lock deleted file mode 100644 index beb92f0677..0000000000 --- a/examples/react-fast-refresh-test/bun.lock +++ /dev/null @@ -1,2566 +0,0 @@ -{ - "lockfileVersion": 1, - "workspaces": { - "": { - "name": "simple-react", - "dependencies": { - "@emotion/css": "^11.1.3", - "@vitejs/plugin-react-refresh": "^1.3.3", - "antd": "^4.16.1", - "left-pad": "^1.3.0", - "next": "^11.0.0", - "parcel": "2.0.0-beta.3", - "react": "^17.0.2", - "react-bootstrap": "^1.6.1", - "react-dom": "^17.0.2", - "react-form": "^4.0.1", - "react-hook-form": "^7.8.3", - }, - "devDependencies": { - "@snowpack/plugin-react-refresh": "^2.5.0", - "typescript": "^4.3.4", - }, - }, - }, - "packages": { - "@ampproject/remapping": ["@ampproject/remapping@2.2.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w=="], - - "@ant-design/colors": ["@ant-design/colors@6.0.0", "", { "dependencies": { "@ctrl/tinycolor": "^3.4.0" } }, "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ=="], - - "@ant-design/icons": ["@ant-design/icons@4.8.0", "", { "dependencies": { "@ant-design/colors": "^6.0.0", "@ant-design/icons-svg": "^4.2.1", "@babel/runtime": "^7.11.2", "classnames": "^2.2.6", "rc-util": "^5.9.4" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-T89P2jG2vM7OJ0IfGx2+9FC5sQjtTzRSz+mCHTXkFn/ELZc2YpfStmYHmqzq2Jx55J0F7+O6i5/ZKFSVNWCKNg=="], - - "@ant-design/icons-svg": ["@ant-design/icons-svg@4.2.1", "", {}, "sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw=="], - - "@ant-design/react-slick": ["@ant-design/react-slick@0.29.2", "", { "dependencies": { "@babel/runtime": "^7.10.4", "classnames": "^2.2.5", "json2mq": "^0.2.0", "lodash": "^4.17.21", "resize-observer-polyfill": "^1.5.1" }, "peerDependencies": { "react": ">=16.9.0" } }, "sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA=="], - - "@babel/code-frame": ["@babel/code-frame@7.18.6", "", { "dependencies": { "@babel/highlight": "^7.18.6" } }, "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q=="], - - "@babel/compat-data": ["@babel/compat-data@7.20.14", "", {}, "sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw=="], - - "@babel/core": ["@babel/core@7.20.12", "", { "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-module-transforms": "^7.20.11", "@babel/helpers": "^7.20.7", "@babel/parser": "^7.20.7", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.12", "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" } }, "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg=="], - - "@babel/generator": ["@babel/generator@7.20.14", "", { "dependencies": { "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } }, "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg=="], - - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.20.7", "", { "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ=="], - - "@babel/helper-environment-visitor": ["@babel/helper-environment-visitor@7.18.9", "", {}, "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg=="], - - "@babel/helper-function-name": ["@babel/helper-function-name@7.19.0", "", { "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" } }, "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w=="], - - "@babel/helper-hoist-variables": ["@babel/helper-hoist-variables@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q=="], - - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], - - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.20.11", "", { "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.10", "@babel/types": "^7.20.7" } }, "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg=="], - - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.20.2", "", {}, "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="], - - "@babel/helper-simple-access": ["@babel/helper-simple-access@7.20.2", "", { "dependencies": { "@babel/types": "^7.20.2" } }, "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA=="], - - "@babel/helper-split-export-declaration": ["@babel/helper-split-export-declaration@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA=="], - - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.19.4", "", {}, "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.19.1", "", {}, "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="], - - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.18.6", "", {}, "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="], - - "@babel/helpers": ["@babel/helpers@7.20.13", "", { "dependencies": { "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.13", "@babel/types": "^7.20.7" } }, "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg=="], - - "@babel/highlight": ["@babel/highlight@7.18.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g=="], - - "@babel/parser": ["@babel/parser@7.20.15", "", { "bin": "./bin/babel-parser.js" }, "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg=="], - - "@babel/plugin-syntax-class-properties": ["@babel/plugin-syntax-class-properties@7.12.13", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA=="], - - "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.18.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A=="], - - "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw=="], - - "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.19.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.19.0", "@babel/plugin-syntax-flow": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-sgeMlNaQVbCSpgLSKP4ZZKfsJVnFnNQlUSk6gPYzR/q7tzCgQF2t8RBKAP6cKJeZdveei7Q7Jm527xepI8lNLg=="], - - "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.18.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig=="], - - "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.19.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.19.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ=="], - - "@babel/runtime": ["@babel/runtime@7.20.13", "", { "dependencies": { "regenerator-runtime": "^0.13.11" } }, "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA=="], - - "@babel/template": ["@babel/template@7.20.7", "", { "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7" } }, "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw=="], - - "@babel/traverse": ["@babel/traverse@7.20.13", "", { "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/parser": "^7.20.13", "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" } }, "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ=="], - - "@babel/types": ["@babel/types@7.20.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.19.4", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg=="], - - "@ctrl/tinycolor": ["@ctrl/tinycolor@3.6.0", "", {}, "sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ=="], - - "@emotion/babel-plugin": ["@emotion/babel-plugin@11.10.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.0", "@emotion/memoize": "^0.8.0", "@emotion/serialize": "^1.1.1", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.1.3" } }, "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ=="], - - "@emotion/cache": ["@emotion/cache@11.10.5", "", { "dependencies": { "@emotion/memoize": "^0.8.0", "@emotion/sheet": "^1.2.1", "@emotion/utils": "^1.2.0", "@emotion/weak-memoize": "^0.3.0", "stylis": "4.1.3" } }, "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA=="], - - "@emotion/css": ["@emotion/css@11.10.6", "", { "dependencies": { "@emotion/babel-plugin": "^11.10.6", "@emotion/cache": "^11.10.5", "@emotion/serialize": "^1.1.1", "@emotion/sheet": "^1.2.1", "@emotion/utils": "^1.2.0" } }, "sha512-88Sr+3heKAKpj9PCqq5A1hAmAkoSIvwEq1O2TwDij7fUtsJpdkV4jMTISSTouFeRvsGvXIpuSuDQ4C1YdfNGXw=="], - - "@emotion/hash": ["@emotion/hash@0.9.0", "", {}, "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="], - - "@emotion/memoize": ["@emotion/memoize@0.8.0", "", {}, "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="], - - "@emotion/serialize": ["@emotion/serialize@1.1.1", "", { "dependencies": { "@emotion/hash": "^0.9.0", "@emotion/memoize": "^0.8.0", "@emotion/unitless": "^0.8.0", "@emotion/utils": "^1.2.0", "csstype": "^3.0.2" } }, "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA=="], - - "@emotion/sheet": ["@emotion/sheet@1.2.1", "", {}, "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA=="], - - "@emotion/unitless": ["@emotion/unitless@0.8.0", "", {}, "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="], - - "@emotion/utils": ["@emotion/utils@1.2.0", "", {}, "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="], - - "@emotion/weak-memoize": ["@emotion/weak-memoize@0.3.0", "", {}, "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="], - - "@hapi/accept": ["@hapi/accept@5.0.2", "", { "dependencies": { "@hapi/boom": "9.x.x", "@hapi/hoek": "9.x.x" } }, "sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw=="], - - "@hapi/boom": ["@hapi/boom@9.1.4", "", { "dependencies": { "@hapi/hoek": "9.x.x" } }, "sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw=="], - - "@hapi/hoek": ["@hapi/hoek@9.3.0", "", {}, "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="], - - "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], - - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.1.1", "", { "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w=="], - - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.0", "", {}, "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="], - - "@jridgewell/set-array": ["@jridgewell/set-array@1.1.2", "", {}, "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="], - - "@jridgewell/source-map": ["@jridgewell/source-map@0.3.2", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.14", "", {}, "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="], - - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.17", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g=="], - - "@napi-rs/triples": ["@napi-rs/triples@1.1.0", "", {}, "sha512-XQr74QaLeMiqhStEhLn1im9EOMnkypp7MZOwQhGzqp2Weu5eQJbpPxWxixxlYRKWPOmJjsk6qYfYH9kq43yc2w=="], - - "@next/env": ["@next/env@11.1.4", "", {}, "sha512-vEW+fSulzZams4nYmcX9LByb1moMBlkwOAVf0eF+44u+1N/h7HDeznPBWIjEfihzTku8rdLB0k7u8VT8AGtNkQ=="], - - "@next/polyfill-module": ["@next/polyfill-module@11.1.4", "", {}, "sha512-CY3bOSQf9Dy3+34dFjFbOdg3DRXIGfujb54D/AVO83ajyQczRZ3xdU0i5VV0eSR6B56ktVy3/aelOffpTUq6LA=="], - - "@next/react-dev-overlay": ["@next/react-dev-overlay@11.1.4", "", { "dependencies": { "@babel/code-frame": "7.12.11", "anser": "1.4.9", "chalk": "4.0.0", "classnames": "2.2.6", "css.escape": "1.5.1", "data-uri-to-buffer": "3.0.1", "platform": "1.3.6", "shell-quote": "1.7.2", "source-map": "0.8.0-beta.0", "stacktrace-parser": "0.1.10", "strip-ansi": "6.0.0" }, "peerDependencies": { "react": "^17.0.2", "react-dom": "^17.0.2" } }, "sha512-8/9JflJwRXEvVb6cKCWgRTOmALzDJHpWD5diRbtXWsllqxcMBjtscgnO4PaK+9QyZnSYSUbn0zZUZvxOXOTE1Q=="], - - "@next/react-refresh-utils": ["@next/react-refresh-utils@11.1.4", "", { "peerDependencies": { "react-refresh": "0.8.3", "webpack": "^4 || ^5" }, "optionalPeers": ["webpack"] }, "sha512-jTme207yEV4On9Gk0QJYK2N3kfKVBx17lLOL3qSjqNbqk1TnE51xvzogOCQXNABbzQlBY+J/NN+eylPS4QOKwA=="], - - "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@11.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jt8dMtIRWnJjRYLid6NWCxXzXdpr9VFT/vhDp8ioh+TtOR0UKPHMxei6R4GA3RqoyPEfFcSNmkG7OtyqCSxNIw=="], - - "@next/swc-darwin-x64": ["@next/swc-darwin-x64@11.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-5i9tOQNO8kawwggHvQUVR3a5KzIGaE2dw1g1kL//z/N840djvGseHrJSFEGdP1c35gM+dSGPpAKHmeBKrwHM8g=="], - - "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@11.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-QfVuXugxBkCUHN9yD/VZ1xqszcMlBDj6vrbRiQvmWuyNo39ON6HqGn3jDwVrTHc9oKo2a0XInm+0zEnQeDmjSw=="], - - "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@11.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-7MPXYWsCo5qGZXyyJwBLvQkYi0hKARtpjGxjt/mdxn7A7O+jKJgAuxgOo/lnZIiXfbJzxRnSD8k6WkUwN0IVmg=="], - - "@node-rs/helper": ["@node-rs/helper@1.2.1", "", { "dependencies": { "@napi-rs/triples": "^1.0.3" } }, "sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg=="], - - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - - "@parcel/babel-ast-utils": ["@parcel/babel-ast-utils@2.0.0-beta.3", "", { "dependencies": { "@babel/parser": "^7.0.0", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "astring": "^1.6.2" } }, "sha512-C8hXpZsgYP2UjskNmx8a25EScPWKVo06MDKXGPa9a4DoFDNBAO+H5WXAd7IOkdYnAmac7j+Bii1MdcUoH4ipUw=="], - - "@parcel/bundler-default": ["@parcel/bundler-default@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1" } }, "sha512-uHD1es4RlKFZPc8fFbiO2g5Lnxt/ccIh9KlsCBjdtxPhioJuKMSdh+CFNx0JJXfQT6rgpNhbNMqqa+eDOVU8yQ=="], - - "@parcel/cache": ["@parcel/cache@2.0.0-beta.3", "", { "dependencies": { "@parcel/logger": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3" }, "peerDependencies": { "@parcel/core": "^2.0.0-alpha.3.1" } }, "sha512-FD5NWBRXeKsuP4jXsWlDOTQriFJzU1flRoYoKPeuUGLKfM9WZ+RV37NOXvIeR6mrAnytXDx1q+fsxlA7/0AlEQ=="], - - "@parcel/codeframe": ["@parcel/codeframe@2.0.0-beta.3", "", { "dependencies": { "chalk": "^4.1.0", "emphasize": "^4.2.0", "slice-ansi": "^4.0.0", "string-width": "^4.2.0" } }, "sha512-IpOnHqnWD9Fcn1suGLwPMvs5wsLaL3M0PHvNKScMZgUelPtgpUPalDyyA2ImgO5Vllon4tTeLLt7246Pvyy5OQ=="], - - "@parcel/config-default": ["@parcel/config-default@2.0.0-beta.3", "", { "dependencies": { "@parcel/bundler-default": "2.0.0-beta.3", "@parcel/namer-default": "2.0.0-beta.3", "@parcel/optimizer-cssnano": "2.0.0-beta.3", "@parcel/optimizer-htmlnano": "2.0.0-beta.3", "@parcel/optimizer-terser": "2.0.0-beta.3", "@parcel/packager-css": "2.0.0-beta.3", "@parcel/packager-html": "2.0.0-beta.3", "@parcel/packager-js": "2.0.0-beta.3", "@parcel/packager-raw": "2.0.0-beta.3", "@parcel/reporter-dev-server": "2.0.0-beta.3", "@parcel/resolver-default": "2.0.0-beta.3", "@parcel/runtime-browser-hmr": "2.0.0-beta.3", "@parcel/runtime-js": "2.0.0-beta.3", "@parcel/runtime-react-refresh": "2.0.0-beta.3", "@parcel/transformer-babel": "2.0.0-beta.3", "@parcel/transformer-css": "2.0.0-beta.3", "@parcel/transformer-html": "2.0.0-beta.3", "@parcel/transformer-js": "2.0.0-beta.3", "@parcel/transformer-json": "2.0.0-beta.3", "@parcel/transformer-postcss": "2.0.0-beta.3", "@parcel/transformer-posthtml": "2.0.0-beta.3", "@parcel/transformer-raw": "2.0.0-beta.3", "@parcel/transformer-react-refresh-wrap": "2.0.0-beta.3" }, "peerDependencies": { "@parcel/core": "^2.0.0-alpha.3.1" } }, "sha512-uVBhKsP2aEG7TX7TtykZ/8n1Fe1VnrPBygPnT6FQoU4to8kWeM3lm0MRNXotJ1WYJr5yLkiugVTzxXqim8lwuw=="], - - "@parcel/core": ["@parcel/core@2.0.0-beta.3", "", { "dependencies": { "@parcel/cache": "2.0.0-beta.3", "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/events": "2.0.0-beta.3", "@parcel/fs": "2.0.0-beta.3", "@parcel/logger": "2.0.0-beta.3", "@parcel/package-manager": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/types": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "@parcel/workers": "2.0.0-beta.3", "abortcontroller-polyfill": "^1.1.9", "base-x": "^3.0.8", "browserslist": "^4.6.6", "clone": "^2.1.1", "dotenv": "^7.0.0", "dotenv-expand": "^5.1.0", "json-source-map": "^0.6.1", "json5": "^1.0.1", "micromatch": "^4.0.2", "nullthrows": "^1.1.1", "querystring": "^0.2.0", "semver": "^5.4.1" } }, "sha512-yUtnowQ3YkwgeWngaD0wiTFsW+EGuIqat5Afujvq5Q/XJczxpQFfhqVkHRiz39V0OXvUINaCZieaHlU6HQI6Fw=="], - - "@parcel/diagnostic": ["@parcel/diagnostic@2.0.0-beta.3", "", { "dependencies": { "json-source-map": "^0.6.1", "nullthrows": "^1.1.1" } }, "sha512-g+KYJglJ5fmq/hiP0RKZCfrNzEnH24SqhvPPS9OnVizcyCnWsj8rBK++J5h6iEsHfFCXjspr7J2457y4X9o7aA=="], - - "@parcel/events": ["@parcel/events@2.0.0-beta.3", "", {}, "sha512-UTCjozKoRNa+gFYkjId6t9GoLcQrMkLtD+uS9gVsHYnEgAkWdWn0qdi2CN1Vt/Pl/+gdd4A/vfcyD8f7xIQx4g=="], - - "@parcel/fs": ["@parcel/fs@2.0.0-beta.3", "", { "dependencies": { "@parcel/fs-search": "2.0.0-beta.3", "@parcel/fs-write-stream-atomic": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "@parcel/watcher": "2.0.0-alpha.10", "@parcel/workers": "2.0.0-beta.3", "graceful-fs": "^4.2.4", "mkdirp": "^0.5.1", "ncp": "^2.0.0", "nullthrows": "^1.1.1", "rimraf": "^3.0.2" }, "peerDependencies": { "@parcel/core": "^2.0.0-alpha.3.1" } }, "sha512-76YdRmqkRldr6MdyETrID6Y+0hXraQ4BTFJixewfdTmrDwHN7RHN/IOw8GxtDJ7XDX9skHnvT/NLYnnbs45PKw=="], - - "@parcel/fs-search": ["@parcel/fs-search@2.0.0-beta.3", "", { "dependencies": { "detect-libc": "^1.0.3" } }, "sha512-DId5pEv+vMiMwIT9XhcXR2Cq7Y8nypZCo89vXK8gnqfUsKMKGPuQRbKneS00co8ulflMl4qrprlmjzOQhAPyqQ=="], - - "@parcel/fs-write-stream-atomic": ["@parcel/fs-write-stream-atomic@2.0.0-beta.3", "", { "dependencies": { "graceful-fs": "^4.1.2", "iferr": "^1.0.2", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" } }, "sha512-gU6N845XLvHtOd93FO9WwW0Ld2NArdaMrH+m1hLztnaxcsGkk7TUE2ObeJyJXPdG+ZvOwFh/viewPXXGDA+byA=="], - - "@parcel/logger": ["@parcel/logger@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/events": "2.0.0-beta.3" } }, "sha512-6JDsgYjKneXC8dlwgiZqRQ7yo3hnxOan1C3E0XEcpncM6keYLHTSxBYIFxs8xXN33gTq7kZgm7KMraHe91pbnw=="], - - "@parcel/markdown-ansi": ["@parcel/markdown-ansi@2.0.0-beta.3", "", { "dependencies": { "chalk": "^4.1.0" } }, "sha512-j7UsvR145jF+F+p7eVKXkhfwEKKMRMgdZr4HE+6obnHjQZu6J/UHNcSRU8xbLmXyV6qGv7LUdztHrHZGYg19eA=="], - - "@parcel/namer-default": ["@parcel/namer-default@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "nullthrows": "^1.1.1" } }, "sha512-TbldmO5M2kHvBFabVkJjl463qQrAPtszxm0xyZSQ5wtp+IguO4h1I1ms3OrsjZLSFEiZ4DqOMvc6qtW32Qyoxg=="], - - "@parcel/node-libs-browser": ["@parcel/node-libs-browser@2.0.0-beta.3", "", { "dependencies": { "assert": "^2.0.0", "browserify-zlib": "^0.2.0", "buffer": "^5.5.0", "console-browserify": "^1.2.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.12.0", "domain-browser": "^3.5.0", "events": "^3.1.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "^1.0.0", "process": "^0.11.10", "punycode": "^1.4.1", "querystring-es3": "^0.2.1", "readable-stream": "^3.6.0", "stream-http": "^3.1.0", "string_decoder": "^1.3.0", "timers-browserify": "^2.0.11", "tty-browserify": "^0.0.1", "url": "^0.11.0", "util": "^0.12.3", "vm-browserify": "^1.1.2" } }, "sha512-lyhIiZaZ5EPPaFz7WG4P/Sxj6VE0GQoucZV2vPyJXmGxbO7SUgpT2FLuIM7jHeqt89gJv6Hyfu5K1vdF69UHTw=="], - - "@parcel/node-resolver-core": ["@parcel/node-resolver-core@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/node-libs-browser": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "micromatch": "^3.0.4", "nullthrows": "^1.1.1", "querystring": "^0.2.0" } }, "sha512-iuI8GOfS7vJBLH1boqhcVjgLPmFqZ70a3WkgUSEGzCsVvAx9d907pKnF5CufKVrgi6U+2tjMgfci5dKlneleNw=="], - - "@parcel/optimizer-cssnano": ["@parcel/optimizer-cssnano@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "cssnano": "^4.1.10", "postcss": "^8.0.5" } }, "sha512-BcEqC+f430Ed3zeAFHY2k6ZZaMtqbOFuPcZ7DPRzdk0C3MDnt/csPuXLz6zx7UAKBizxUr5kuetCIdAE300kIw=="], - - "@parcel/optimizer-htmlnano": ["@parcel/optimizer-htmlnano@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "htmlnano": "^0.2.2", "nullthrows": "^1.1.1", "posthtml": "^0.15.1" } }, "sha512-RJv17A9CYOm9KiebRSokOX54W4d5d83gOE31Tbn1GzmIzFVIRha0a6jrXBK+kxkikk3/jdrzkSI0bBom12pGQw=="], - - "@parcel/optimizer-terser": ["@parcel/optimizer-terser@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1", "terser": "^5.2.0" } }, "sha512-vq21XlmxbRoa6vscGTyexU6IEYeBnQl8ZYf27fki3L+hRL98qtn1uI0GC0963B+DYpl3YngTAp0o6XSCQj4hrg=="], - - "@parcel/package-manager": ["@parcel/package-manager@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/fs": "2.0.0-beta.3", "@parcel/logger": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "@parcel/workers": "2.0.0-beta.3", "command-exists": "^1.2.6", "cross-spawn": "^6.0.4", "nullthrows": "^1.1.1", "semver": "^5.4.1", "split2": "^3.1.1" }, "peerDependencies": { "@parcel/core": "^2.0.0-alpha.3.1" } }, "sha512-PsA4kL0JnUXg2EY5C223wR6BhGwFpq8kioerKm33L+JmsbqQruzeMgB/OD5SPx7XVtslB0dWv6yeoOI/nv6l4w=="], - - "@parcel/packager-css": ["@parcel/packager-css@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1", "postcss": "^8.2.1" } }, "sha512-UDS0KtjnvenCoCDz/6B37nSO67E/1zOLmLSxVszdxjJWqpsNwIw4wHbBosPAeqc/m456jV+gB34vnorU7AD9vg=="], - - "@parcel/packager-html": ["@parcel/packager-html@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/types": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1", "posthtml": "^0.15.1" } }, "sha512-Edvn17Gq92V3KGVnPgnKoTP5IwVe0Y3fGMim9reUeXg2ysSYLTnlFZ/Jnbx9O/LxK5cwZuHPRLu7iFQNAUuuNg=="], - - "@parcel/packager-js": ["@parcel/packager-js@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "globals": "^13.2.0", "nullthrows": "^1.1.1" } }, "sha512-zq1rp4JLb31c5nJdbXTw0eXWEoQTqGku1mbeSTt5DImTBqRNWBD5sdR0sNbqbUbC1VH9akvjvVQXgx5nQGRYKw=="], - - "@parcel/packager-raw": ["@parcel/packager-raw@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3" } }, "sha512-oJ+25lW58oBOHctumosHj9jvSn16qOgv5GlOckgLrZuJ5S1xcGGM3qDdbFUGBd0bWGvP8JOlDLCLCf1hFJUA/Q=="], - - "@parcel/plugin": ["@parcel/plugin@2.0.0-beta.3", "", { "dependencies": { "@parcel/types": "2.0.0-beta.3" } }, "sha512-BeJBftoRTgkJP4TfEMIDyvGAT3fW4/D6R14b6rTdn6/M4feAXwLlxGdadTyR5z2JlsaY/JdVr3l0pUInYbFcZw=="], - - "@parcel/reporter-cli": ["@parcel/reporter-cli@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/types": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "chalk": "^4.1.0", "filesize": "^6.1.0", "nullthrows": "^1.1.1", "ora": "^5.2.0", "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "term-size": "^2.2.1" } }, "sha512-PxSkK6feTf1p5ec7hlD2kegCA4EoiAXfyyxf32XGo7HRbto+xKiYLK+e3C52n4znowO1pRdtI0ck+YCQeppS4Q=="], - - "@parcel/reporter-dev-server": ["@parcel/reporter-dev-server@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "connect": "^3.7.0", "ejs": "^2.6.1", "http-proxy-middleware": "^1.0.0", "nullthrows": "^1.1.1", "serve-handler": "^6.0.0", "ws": "^7.0.0" } }, "sha512-tYBYO6fcaqOlyEJV1iPiqBgWM1J8suA7PD8aSsQr0PjHHb81XMKELkDc802YlJMPtdmiwELVAiY2iS6qa8ooFg=="], - - "@parcel/resolver-default": ["@parcel/resolver-default@2.0.0-beta.3", "", { "dependencies": { "@parcel/node-resolver-core": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3" } }, "sha512-EvqcH/1qJZQoPU80upVYqqJ3U9sxiACz97wFKm1S7gqQRQH1acxOHstRGe/iqgTMFh6KHoydY+QXRiudqJr7nQ=="], - - "@parcel/runtime-browser-hmr": ["@parcel/runtime-browser-hmr@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3" } }, "sha512-T4ZGEd4bcz6zE+mIOxfXb/u/1wVbLOkHPs3ydXWAe7nOQXF+BC4yZXGC0vePJ4HX2X+QNg//cA0owMOshHE83Q=="], - - "@parcel/runtime-js": ["@parcel/runtime-js@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1" } }, "sha512-JkWlfkO7E76ayksFTdk9Ek633YvBqHoMJ8UwvEJMjUn42v8hLZQUHKAFoUZRYqzjZOub0BVdGwrvbuf1dV90ig=="], - - "@parcel/runtime-react-refresh": ["@parcel/runtime-react-refresh@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "react-refresh": "^0.9.0" } }, "sha512-99VdouRuDM1IekY0b3onCHd9zrkM93Gl9xZgBWwJpdC/jcrvdNxgSb0PwQg19YVfjCn5MM/ou7yybE8xL3aU3A=="], - - "@parcel/source-map": ["@parcel/source-map@2.0.0-rc.1.0", "", { "dependencies": { "detect-libc": "^1.0.3", "globby": "^11.0.3" } }, "sha512-X+1Eef2eVLqGbUSBjP6n2tNnqQv0HyLu6j324hPSqqA8JeHk3X1M5V6FzUe9W2RbCF1Y49VvlXRfC6BqMrZyEw=="], - - "@parcel/transformer-babel": ["@parcel/transformer-babel@2.0.0-beta.3", "", { "dependencies": { "@babel/core": "^7.12.0", "@babel/generator": "^7.9.0", "@babel/helper-compilation-targets": "^7.8.4", "@babel/plugin-transform-flow-strip-types": "^7.0.0", "@babel/traverse": "^7.0.0", "@parcel/babel-ast-utils": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "browserslist": "^4.6.6", "core-js": "^3.2.1", "nullthrows": "^1.1.1", "semver": "^5.7.0" } }, "sha512-yvpQ51ih1G1sgQjkgQuB+pAXnbaJmIbm1iKRGyTwc6Ucmz0PIGmrwRM4NBu3KccOl1/1BthRZTMsKvuuaLZL8w=="], - - "@parcel/transformer-css": ["@parcel/transformer-css@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1", "postcss": "^8.2.1", "postcss-value-parser": "^4.1.0", "semver": "^5.4.1" } }, "sha512-1v76u4VuWAQ51HqAuxq+5Tw4spzZAtrUIC0n/CNQt9i15tx9Q61zlhsB2YNYMqJG/shyMTZb9ioNl1t9KD6iaA=="], - - "@parcel/transformer-html": ["@parcel/transformer-html@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1", "posthtml": "^0.15.1", "posthtml-parser": "^0.6.0", "posthtml-render": "^1.4.0", "semver": "^5.4.1" } }, "sha512-QIH1eTXjG1qKuWak6xw3iU/GK7HOltTO84InJUSLaaUxYbgh1DeXhsKloJmWgdZZx4eZOopf58JUM7OoEcFwtg=="], - - "@parcel/transformer-js": ["@parcel/transformer-js@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/plugin": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "@parcel/utils": "2.0.0-beta.3", "@swc/helpers": "^0.2.11", "browserslist": "^4.6.6", "detect-libc": "^1.0.3", "micromatch": "^4.0.2", "nullthrows": "^1.1.1", "semver": "^5.4.1" } }, "sha512-lRDc9HqB7o/EpMTYMfymyfp3kS2o8EGQlpPOVQGeTGCnEChNxX5qwbMchXU/I03bKYGgpgn3rMx+CJja2UEZhw=="], - - "@parcel/transformer-json": ["@parcel/transformer-json@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "json5": "^2.1.0" } }, "sha512-kig1K1CaSVJG7TaULwyVQKnWqjqNzFEwFweVRVgs1sG+uGrySJkJTiVW1B4wquNTT9pJwQMXtdQs5alyyhEweA=="], - - "@parcel/transformer-postcss": ["@parcel/transformer-postcss@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "clone": "^2.1.1", "css-modules-loader-core": "^1.1.0", "nullthrows": "^1.1.1", "postcss-modules": "^3.2.2", "postcss-value-parser": "^4.1.0", "semver": "^5.4.1" } }, "sha512-zl5GlcdSBc3DyrX1StafT5qJNhpJiWHntMSKaIOta8SL7/1olvUV7AuQeRvC1OmNFfdVSHQO+T/vnByER3EklQ=="], - - "@parcel/transformer-posthtml": ["@parcel/transformer-posthtml@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "nullthrows": "^1.1.1", "posthtml": "^0.15.1", "posthtml-parser": "^0.6.0", "posthtml-render": "^1.4.0", "semver": "^5.4.1" } }, "sha512-xl5m0PQ5cTCf77Mys5e17gGqXcJ2YANwrplgtOhv12W/RVMHpZhQLHycar3OZ3gC9qkAuA2qFZj7ArO78vEMPg=="], - - "@parcel/transformer-raw": ["@parcel/transformer-raw@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3" } }, "sha512-LjeqMZIp363Cz2JqV2Z02sCX4dDZGwqTU5YnENQ+YyOmchJjvOJxgb/0XaDnQkjwoe5LVqoZkDXYvTAg/GScNg=="], - - "@parcel/transformer-react-refresh-wrap": ["@parcel/transformer-react-refresh-wrap@2.0.0-beta.3", "", { "dependencies": { "@parcel/plugin": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "react-refresh": "^0.9.0" } }, "sha512-K53j6YmIpP5K/0sONNlBUkCXoQK+6KfNzB8uViaCCkDwhSA+u3ukvpRur71ReEsiVaL0z8yqzD37Ekyl448QvA=="], - - "@parcel/types": ["@parcel/types@2.0.0-beta.3", "", {}, "sha512-5o/6KmYVU68+4IhauELMDz/kwkcoMGAB7veUX5hmH4nVNw6T05ZUHF0Te1OILASdAj67+XRAqeSA/+aWOhW/AA=="], - - "@parcel/utils": ["@parcel/utils@2.0.0-beta.3", "", { "dependencies": { "@iarna/toml": "^2.2.0", "@parcel/codeframe": "2.0.0-beta.3", "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/logger": "2.0.0-beta.3", "@parcel/markdown-ansi": "2.0.0-beta.3", "@parcel/source-map": "2.0.0-rc.1.0", "ansi-html": "^0.0.7", "chalk": "^4.1.0", "clone": "^2.1.1", "fast-glob": "3.1.1", "fastest-levenshtein": "^1.0.8", "is-glob": "^4.0.0", "is-url": "^1.2.2", "json5": "^1.0.1", "lru-cache": "^6.0.0", "micromatch": "^4.0.2", "node-forge": "^0.10.0", "nullthrows": "^1.1.1", "open": "^7.0.3" } }, "sha512-a5DKWcEkOj/BKrftXoJV+CvFQn5Axmmmx3kk1J9QM+4sTclD7pdyN3r2L7sLIFkGOtpk55E7IgCDMtj3LpGm6w=="], - - "@parcel/watcher": ["@parcel/watcher@2.0.0-alpha.10", "", { "dependencies": { "node-addon-api": "^3.0.2", "node-gyp-build": "^4.2.3" } }, "sha512-8uA7Tmx/1XvmUdGzksg0+oN7uj24pXFFnKJqZr3L3mgYjdrL7CMs3PRIHv1k3LUz/hNRsb/p3qxztSkWz1IGZA=="], - - "@parcel/workers": ["@parcel/workers@2.0.0-beta.3", "", { "dependencies": { "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/logger": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "chrome-trace-event": "^1.0.2", "nullthrows": "^1.1.1" }, "peerDependencies": { "@parcel/core": "^2.0.0-alpha.3.1" } }, "sha512-EEs0qmTj7FzcwhETFJ0wE/zGYK1xQH1sOACu1slFS9QVPpUGvGGHs9Kc1PGNiEkbTD1xMReRXETc6vf90IymCg=="], - - "@popperjs/core": ["@popperjs/core@2.11.6", "", {}, "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="], - - "@rc-component/portal": ["@rc-component/portal@1.0.0-10", "", { "dependencies": { "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "rc-util": "^5.8.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Y4JgfSZtUZaM8C5ZYFtbJVOkRrR4QVIThd/VbPMRPDI5Mv6xnOAkjg50UbB8uYH7pclCqIBoc17djbAzo12r3w=="], - - "@restart/context": ["@restart/context@2.1.4", "", { "peerDependencies": { "react": ">=16.3.2" } }, "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="], - - "@restart/hooks": ["@restart/hooks@0.4.9", "", { "dependencies": { "dequal": "^2.0.2" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ=="], - - "@rollup/pluginutils": ["@rollup/pluginutils@4.2.1", "", { "dependencies": { "estree-walker": "^2.0.1", "picomatch": "^2.2.2" } }, "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ=="], - - "@snowpack/plugin-react-refresh": ["@snowpack/plugin-react-refresh@2.5.0", "", { "dependencies": { "@babel/core": "^7.0.0", "@babel/plugin-syntax-class-properties": "^7.10.0", "react-refresh": "^0.9.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-3rYkwayAA+65IIYLXMEFqQwtBGbII9IidMJo1yXuj35kTEg9TdZrofoqcHaSts2sv2Nz0TD6v7BWRPdvCU0uIw=="], - - "@swc/helpers": ["@swc/helpers@0.2.14", "", {}, "sha512-wpCQMhf5p5GhNg2MmGKXzUNwxe7zRiCsmqYsamez2beP7mKPCSiu+BjZcdN95yYSzO857kr0VfQewmGpS77nqA=="], - - "@types/http-proxy": ["@types/http-proxy@1.17.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw=="], - - "@types/invariant": ["@types/invariant@2.2.35", "", {}, "sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg=="], - - "@types/node": ["@types/node@18.14.0", "", {}, "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A=="], - - "@types/parse-json": ["@types/parse-json@4.0.0", "", {}, "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="], - - "@types/prop-types": ["@types/prop-types@15.7.5", "", {}, "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="], - - "@types/q": ["@types/q@1.5.5", "", {}, "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ=="], - - "@types/react": ["@types/react@18.0.28", "", { "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew=="], - - "@types/react-transition-group": ["@types/react-transition-group@4.4.5", "", { "dependencies": { "@types/react": "*" } }, "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA=="], - - "@types/scheduler": ["@types/scheduler@0.16.2", "", {}, "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="], - - "@types/warning": ["@types/warning@3.0.0", "", {}, "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA=="], - - "@vitejs/plugin-react-refresh": ["@vitejs/plugin-react-refresh@1.3.6", "", { "dependencies": { "@babel/core": "^7.14.8", "@babel/plugin-transform-react-jsx-self": "^7.14.5", "@babel/plugin-transform-react-jsx-source": "^7.14.5", "@rollup/pluginutils": "^4.1.1", "react-refresh": "^0.10.0" } }, "sha512-iNR/UqhUOmFFxiezt0em9CgmiJBdWR+5jGxB2FihaoJfqGt76kiwaKoVOJVU5NYcDWMdN06LbyN2VIGIoYdsEA=="], - - "abab": ["abab@2.0.6", "", {}, "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="], - - "abortcontroller-polyfill": ["abortcontroller-polyfill@1.7.5", "", {}, "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ=="], - - "acorn": ["acorn@8.8.2", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="], - - "acorn-globals": ["acorn-globals@4.3.4", "", { "dependencies": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" } }, "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A=="], - - "acorn-walk": ["acorn-walk@6.2.0", "", {}, "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="], - - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "alphanum-sort": ["alphanum-sort@1.0.2", "", {}, "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ=="], - - "anser": ["anser@1.4.9", "", {}, "sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA=="], - - "ansi-html": ["ansi-html@0.0.7", "", { "bin": { "ansi-html": "./bin/ansi-html" } }, "sha512-JoAxEa1DfP9m2xfB/y2r/aKcwXNlltr4+0QSBC4TrLfcxyvepX2Pv0t/xpgGV5bGsDzCYV8SzjWgyCW0T9yYbA=="], - - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], - - "antd": ["antd@4.24.8", "", { "dependencies": { "@ant-design/colors": "^6.0.0", "@ant-design/icons": "^4.7.0", "@ant-design/react-slick": "~0.29.1", "@babel/runtime": "^7.18.3", "@ctrl/tinycolor": "^3.4.0", "classnames": "^2.2.6", "copy-to-clipboard": "^3.2.0", "lodash": "^4.17.21", "moment": "^2.29.2", "rc-cascader": "~3.7.0", "rc-checkbox": "~2.3.0", "rc-collapse": "~3.4.2", "rc-dialog": "~9.0.2", "rc-drawer": "~6.1.0", "rc-dropdown": "~4.0.0", "rc-field-form": "~1.27.0", "rc-image": "~5.13.0", "rc-input": "~0.1.4", "rc-input-number": "~7.3.9", "rc-mentions": "~1.13.1", "rc-menu": "~9.8.0", "rc-motion": "^2.6.1", "rc-notification": "~4.6.0", "rc-pagination": "~3.2.0", "rc-picker": "~2.7.0", "rc-progress": "~3.4.1", "rc-rate": "~2.9.0", "rc-resize-observer": "^1.2.0", "rc-segmented": "~2.1.0", "rc-select": "~14.1.13", "rc-slider": "~10.0.0", "rc-steps": "~5.0.0-alpha.2", "rc-switch": "~3.2.0", "rc-table": "~7.26.0", "rc-tabs": "~12.5.6", "rc-textarea": "~0.4.5", "rc-tooltip": "~5.2.0", "rc-tree": "~5.7.0", "rc-tree-select": "~5.5.0", "rc-trigger": "^5.2.10", "rc-upload": "~4.3.0", "rc-util": "^5.22.5", "scroll-into-view-if-needed": "^2.2.25" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-wrNy2Hi27uM3948okG3n2GwzQKBFUn1Qn5mn2I/ALcR28rC6cTjHYOuA248Zl9ECzz3jo4TY2R0SIa+5GZ/zGA=="], - - "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - - "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - - "arr-diff": ["arr-diff@4.0.0", "", {}, "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA=="], - - "arr-flatten": ["arr-flatten@1.1.0", "", {}, "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="], - - "arr-union": ["arr-union@3.1.0", "", {}, "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q=="], - - "array-equal": ["array-equal@1.0.0", "", {}, "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA=="], - - "array-tree-filter": ["array-tree-filter@2.1.0", "", {}, "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="], - - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], - - "array-unique": ["array-unique@0.3.2", "", {}, "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ=="], - - "array.prototype.reduce": ["array.prototype.reduce@1.0.5", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.20.4", "es-array-method-boxes-properly": "^1.0.0", "is-string": "^1.0.7" } }, "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q=="], - - "asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="], - - "asn1.js": ["asn1.js@5.4.1", "", { "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "safer-buffer": "^2.1.0" } }, "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA=="], - - "assert": ["assert@2.0.0", "", { "dependencies": { "es6-object-assign": "^1.1.0", "is-nan": "^1.2.1", "object-is": "^1.0.1", "util": "^0.12.0" } }, "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A=="], - - "assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="], - - "assign-symbols": ["assign-symbols@1.0.0", "", {}, "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="], - - "ast-types": ["ast-types@0.13.2", "", {}, "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA=="], - - "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], - - "astring": ["astring@1.8.4", "", { "bin": { "astring": "bin/astring" } }, "sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw=="], - - "async-limiter": ["async-limiter@1.0.1", "", {}, "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="], - - "async-validator": ["async-validator@4.2.5", "", {}, "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="], - - "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], - - "atob": ["atob@2.1.2", "", { "bin": { "atob": "bin/atob.js" } }, "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="], - - "available-typed-arrays": ["available-typed-arrays@1.0.5", "", {}, "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="], - - "aws-sign2": ["aws-sign2@0.7.0", "", {}, "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="], - - "aws4": ["aws4@1.12.0", "", {}, "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="], - - "babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "base": ["base@0.11.2", "", { "dependencies": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", "component-emitter": "^1.2.1", "define-property": "^1.0.0", "isobject": "^3.0.1", "mixin-deep": "^1.2.0", "pascalcase": "^0.1.1" } }, "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg=="], - - "base-x": ["base-x@3.0.9", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ=="], - - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - - "bcrypt-pbkdf": ["bcrypt-pbkdf@1.0.2", "", { "dependencies": { "tweetnacl": "^0.14.3" } }, "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w=="], - - "big.js": ["big.js@5.2.2", "", {}, "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="], - - "binary-extensions": ["binary-extensions@2.2.0", "", {}, "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="], - - "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], - - "bn.js": ["bn.js@5.2.1", "", {}, "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="], - - "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - - "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - - "braces": ["braces@3.0.2", "", { "dependencies": { "fill-range": "^7.0.1" } }, "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A=="], - - "brorand": ["brorand@1.1.0", "", {}, "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="], - - "browser-process-hrtime": ["browser-process-hrtime@1.0.0", "", {}, "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="], - - "browserify-aes": ["browserify-aes@1.2.0", "", { "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.3", "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA=="], - - "browserify-cipher": ["browserify-cipher@1.0.1", "", { "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", "evp_bytestokey": "^1.0.0" } }, "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w=="], - - "browserify-des": ["browserify-des@1.0.2", "", { "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A=="], - - "browserify-rsa": ["browserify-rsa@4.1.0", "", { "dependencies": { "bn.js": "^5.0.0", "randombytes": "^2.0.1" } }, "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog=="], - - "browserify-sign": ["browserify-sign@4.2.1", "", { "dependencies": { "bn.js": "^5.1.1", "browserify-rsa": "^4.0.1", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", "elliptic": "^6.5.3", "inherits": "^2.0.4", "parse-asn1": "^5.1.5", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" } }, "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg=="], - - "browserify-zlib": ["browserify-zlib@0.2.0", "", { "dependencies": { "pako": "~1.0.5" } }, "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA=="], - - "browserslist": ["browserslist@4.16.6", "", { "dependencies": { "caniuse-lite": "^1.0.30001219", "colorette": "^1.2.2", "electron-to-chromium": "^1.3.723", "escalade": "^3.1.1", "node-releases": "^1.1.71" }, "bin": { "browserslist": "cli.js" } }, "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ=="], - - "buffer": ["buffer@5.6.0", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" } }, "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw=="], - - "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - - "buffer-xor": ["buffer-xor@1.0.3", "", {}, "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ=="], - - "builtin-status-codes": ["builtin-status-codes@3.0.0", "", {}, "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ=="], - - "bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="], - - "cache-base": ["cache-base@1.0.1", "", { "dependencies": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", "get-value": "^2.0.6", "has-value": "^1.0.0", "isobject": "^3.0.1", "set-value": "^2.0.0", "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" } }, "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ=="], - - "call-bind": ["call-bind@1.0.2", "", { "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" } }, "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA=="], - - "caller-callsite": ["caller-callsite@2.0.0", "", { "dependencies": { "callsites": "^2.0.0" } }, "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ=="], - - "caller-path": ["caller-path@2.0.0", "", { "dependencies": { "caller-callsite": "^2.0.0" } }, "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A=="], - - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - - "caniuse-api": ["caniuse-api@3.0.0", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw=="], - - "caniuse-lite": ["caniuse-lite@1.0.30001456", "", {}, "sha512-XFHJY5dUgmpMV25UqaD4kVq2LsiaU5rS8fb0f17pCoXQiQslzmFgnfOxfvo1bTpTqf7dwG/N/05CnLCnOEKmzA=="], - - "caseless": ["caseless@0.12.0", "", {}, "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="], - - "chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], - - "chokidar": ["chokidar@3.5.1", "", { "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.5.0" } }, "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw=="], - - "chrome-trace-event": ["chrome-trace-event@1.0.3", "", {}, "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="], - - "cipher-base": ["cipher-base@1.0.4", "", { "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q=="], - - "class-utils": ["class-utils@0.3.6", "", { "dependencies": { "arr-union": "^3.1.0", "define-property": "^0.2.5", "isobject": "^3.0.0", "static-extend": "^0.1.1" } }, "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg=="], - - "classnames": ["classnames@2.3.2", "", {}, "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="], - - "cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="], - - "cli-spinners": ["cli-spinners@2.7.0", "", {}, "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw=="], - - "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], - - "coa": ["coa@2.0.2", "", { "dependencies": { "@types/q": "^1.5.1", "chalk": "^2.4.1", "q": "^1.1.2" } }, "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA=="], - - "collection-visit": ["collection-visit@1.0.0", "", { "dependencies": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" } }, "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw=="], - - "color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="], - - "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], - - "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], - - "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], - - "colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="], - - "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], - - "command-exists": ["command-exists@1.2.9", "", {}, "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w=="], - - "commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], - - "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], - - "component-emitter": ["component-emitter@1.3.0", "", {}, "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="], - - "compute-scroll-into-view": ["compute-scroll-into-view@1.0.20", "", {}, "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg=="], - - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], - - "console-browserify": ["console-browserify@1.2.0", "", {}, "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="], - - "constants-browserify": ["constants-browserify@1.0.0", "", {}, "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ=="], - - "content-disposition": ["content-disposition@0.5.2", "", {}, "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA=="], - - "convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="], - - "copy-descriptor": ["copy-descriptor@0.1.1", "", {}, "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw=="], - - "copy-to-clipboard": ["copy-to-clipboard@3.3.3", "", { "dependencies": { "toggle-selection": "^1.0.6" } }, "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA=="], - - "core-js": ["core-js@3.28.0", "", {}, "sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw=="], - - "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], - - "cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="], - - "create-ecdh": ["create-ecdh@4.0.4", "", { "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.5.3" } }, "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A=="], - - "create-hash": ["create-hash@1.2.0", "", { "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", "md5.js": "^1.3.4", "ripemd160": "^2.0.1", "sha.js": "^2.4.0" } }, "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg=="], - - "create-hmac": ["create-hmac@1.1.7", "", { "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", "inherits": "^2.0.1", "ripemd160": "^2.0.0", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" } }, "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg=="], - - "cross-spawn": ["cross-spawn@6.0.5", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ=="], - - "crypto-browserify": ["crypto-browserify@3.12.0", "", { "dependencies": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", "create-ecdh": "^4.0.0", "create-hash": "^1.1.0", "create-hmac": "^1.1.0", "diffie-hellman": "^5.0.0", "inherits": "^2.0.1", "pbkdf2": "^3.0.3", "public-encrypt": "^4.0.0", "randombytes": "^2.0.0", "randomfill": "^1.0.3" } }, "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg=="], - - "css-color-names": ["css-color-names@0.0.4", "", {}, "sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q=="], - - "css-declaration-sorter": ["css-declaration-sorter@4.0.1", "", { "dependencies": { "postcss": "^7.0.1", "timsort": "^0.3.0" } }, "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA=="], - - "css-modules-loader-core": ["css-modules-loader-core@1.1.0", "", { "dependencies": { "icss-replace-symbols": "1.1.0", "postcss": "6.0.1", "postcss-modules-extract-imports": "1.1.0", "postcss-modules-local-by-default": "1.2.0", "postcss-modules-scope": "1.1.0", "postcss-modules-values": "1.3.0" } }, "sha512-XWOBwgy5nwBn76aA+6ybUGL/3JBnCtBX9Ay9/OWIpzKYWlVHMazvJ+WtHumfi+xxdPF440cWK7JCYtt8xDifew=="], - - "css-select": ["css-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^3.2.1", "domutils": "^1.7.0", "nth-check": "^1.0.2" } }, "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ=="], - - "css-select-base-adapter": ["css-select-base-adapter@0.1.1", "", {}, "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="], - - "css-selector-tokenizer": ["css-selector-tokenizer@0.7.3", "", { "dependencies": { "cssesc": "^3.0.0", "fastparse": "^1.1.2" } }, "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg=="], - - "css-tree": ["css-tree@1.0.0-alpha.37", "", { "dependencies": { "mdn-data": "2.0.4", "source-map": "^0.6.1" } }, "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg=="], - - "css-what": ["css-what@3.4.2", "", {}, "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ=="], - - "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="], - - "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - - "cssnano": ["cssnano@4.1.11", "", { "dependencies": { "cosmiconfig": "^5.0.0", "cssnano-preset-default": "^4.0.8", "is-resolvable": "^1.0.0", "postcss": "^7.0.0" } }, "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g=="], - - "cssnano-preset-default": ["cssnano-preset-default@4.0.8", "", { "dependencies": { "css-declaration-sorter": "^4.0.1", "cssnano-util-raw-cache": "^4.0.1", "postcss": "^7.0.0", "postcss-calc": "^7.0.1", "postcss-colormin": "^4.0.3", "postcss-convert-values": "^4.0.1", "postcss-discard-comments": "^4.0.2", "postcss-discard-duplicates": "^4.0.2", "postcss-discard-empty": "^4.0.1", "postcss-discard-overridden": "^4.0.1", "postcss-merge-longhand": "^4.0.11", "postcss-merge-rules": "^4.0.3", "postcss-minify-font-values": "^4.0.2", "postcss-minify-gradients": "^4.0.2", "postcss-minify-params": "^4.0.2", "postcss-minify-selectors": "^4.0.2", "postcss-normalize-charset": "^4.0.1", "postcss-normalize-display-values": "^4.0.2", "postcss-normalize-positions": "^4.0.2", "postcss-normalize-repeat-style": "^4.0.2", "postcss-normalize-string": "^4.0.2", "postcss-normalize-timing-functions": "^4.0.2", "postcss-normalize-unicode": "^4.0.1", "postcss-normalize-url": "^4.0.1", "postcss-normalize-whitespace": "^4.0.2", "postcss-ordered-values": "^4.1.2", "postcss-reduce-initial": "^4.0.3", "postcss-reduce-transforms": "^4.0.2", "postcss-svgo": "^4.0.3", "postcss-unique-selectors": "^4.0.1" } }, "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ=="], - - "cssnano-preset-simple": ["cssnano-preset-simple@3.0.2", "", { "dependencies": { "caniuse-lite": "^1.0.30001202" }, "peerDependencies": { "postcss": "^8.2.15" } }, "sha512-7c6EOw3oZshKOZc20Jh+cs2dIKxp0viV043jdal/t1iGVQkoyAQio3rrFWhPgAlkXMu+PRXsslqLhosFTmLhmQ=="], - - "cssnano-simple": ["cssnano-simple@3.0.0", "", { "dependencies": { "cssnano-preset-simple": "^3.0.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "sha512-oU3ueli5Dtwgh0DyeohcIEE00QVfbPR3HzyXdAl89SfnQG3y0/qcpfLVW+jPIh3/rgMZGwuW96rejZGaYE9eUg=="], - - "cssnano-util-get-arguments": ["cssnano-util-get-arguments@4.0.0", "", {}, "sha512-6RIcwmV3/cBMG8Aj5gucQRsJb4vv4I4rn6YjPbVWd5+Pn/fuG+YseGvXGk00XLkoZkaj31QOD7vMUpNPC4FIuw=="], - - "cssnano-util-get-match": ["cssnano-util-get-match@4.0.0", "", {}, "sha512-JPMZ1TSMRUPVIqEalIBNoBtAYbi8okvcFns4O0YIhcdGebeYZK7dMyHJiQ6GqNBA9kE0Hym4Aqym5rPdsV/4Cw=="], - - "cssnano-util-raw-cache": ["cssnano-util-raw-cache@4.0.1", "", { "dependencies": { "postcss": "^7.0.0" } }, "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA=="], - - "cssnano-util-same-parent": ["cssnano-util-same-parent@4.0.1", "", {}, "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q=="], - - "csso": ["csso@4.2.0", "", { "dependencies": { "css-tree": "^1.1.2" } }, "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA=="], - - "cssom": ["cssom@0.3.8", "", {}, "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="], - - "cssstyle": ["cssstyle@1.4.0", "", { "dependencies": { "cssom": "0.3.x" } }, "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA=="], - - "csstype": ["csstype@3.1.1", "", {}, "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="], - - "dashdash": ["dashdash@1.14.1", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g=="], - - "data-uri-to-buffer": ["data-uri-to-buffer@3.0.1", "", {}, "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og=="], - - "data-urls": ["data-urls@1.1.0", "", { "dependencies": { "abab": "^2.0.0", "whatwg-mimetype": "^2.2.0", "whatwg-url": "^7.0.0" } }, "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ=="], - - "date-fns": ["date-fns@2.29.3", "", {}, "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="], - - "dayjs": ["dayjs@1.11.7", "", {}, "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ=="], - - "debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="], - - "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="], - - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - - "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], - - "define-properties": ["define-properties@1.2.0", "", { "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA=="], - - "define-property": ["define-property@2.0.2", "", { "dependencies": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" } }, "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ=="], - - "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], - - "depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], - - "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - - "des.js": ["des.js@1.0.1", "", { "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA=="], - - "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], - - "diffie-hellman": ["diffie-hellman@5.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" } }, "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg=="], - - "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], - - "dom-align": ["dom-align@1.12.4", "", {}, "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw=="], - - "dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="], - - "dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="], - - "domain-browser": ["domain-browser@4.19.0", "", {}, "sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ=="], - - "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], - - "domexception": ["domexception@1.0.1", "", { "dependencies": { "webidl-conversions": "^4.0.2" } }, "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug=="], - - "domhandler": ["domhandler@3.3.0", "", { "dependencies": { "domelementtype": "^2.0.1" } }, "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA=="], - - "domutils": ["domutils@2.8.0", "", { "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" } }, "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A=="], - - "dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="], - - "dotenv": ["dotenv@7.0.0", "", {}, "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g=="], - - "dotenv-expand": ["dotenv-expand@5.1.0", "", {}, "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="], - - "ecc-jsbn": ["ecc-jsbn@0.1.2", "", { "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw=="], - - "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - - "ejs": ["ejs@2.7.4", "", {}, "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="], - - "electron-to-chromium": ["electron-to-chromium@1.4.302", "", {}, "sha512-Uk7C+7aPBryUR1Fwvk9VmipBcN9fVsqBO57jV2ZjTm+IZ6BMNqu7EDVEg2HxCNufk6QcWlFsBkhQyQroB2VWKw=="], - - "elliptic": ["elliptic@6.5.4", "", { "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ=="], - - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "emojis-list": ["emojis-list@2.1.0", "", {}, "sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng=="], - - "emphasize": ["emphasize@4.2.0", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "~10.4.0", "lowlight": "~1.17.0" } }, "sha512-yGKvcFUHlBsUPwlxTlzKLR8+zhpbitkFOMCUxN8fTJng9bdH3WNzUGkhdaGdjndSUgqmMPBN7umfwnUdLz5Axg=="], - - "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - - "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], - - "entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="], - - "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], - - "es-abstract": ["es-abstract@1.21.1", "", { "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "internal-slot": "^1.0.4", "is-array-buffer": "^3.0.1", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", "object-inspect": "^1.12.2", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", "safe-regex-test": "^1.0.0", "string.prototype.trimend": "^1.0.6", "string.prototype.trimstart": "^1.0.6", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.9" } }, "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg=="], - - "es-array-method-boxes-properly": ["es-array-method-boxes-properly@1.0.0", "", {}, "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="], - - "es-set-tostringtag": ["es-set-tostringtag@2.0.1", "", { "dependencies": { "get-intrinsic": "^1.1.3", "has": "^1.0.3", "has-tostringtag": "^1.0.0" } }, "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg=="], - - "es-to-primitive": ["es-to-primitive@1.2.1", "", { "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" } }, "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA=="], - - "es6-object-assign": ["es6-object-assign@1.1.0", "", {}, "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw=="], - - "escalade": ["escalade@3.1.1", "", {}, "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="], - - "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - - "escodegen": ["escodegen@1.14.3", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw=="], - - "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], - - "estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], - - "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - - "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - - "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], - - "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], - - "evp_bytestokey": ["evp_bytestokey@1.0.3", "", { "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" } }, "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA=="], - - "expand-brackets": ["expand-brackets@2.1.4", "", { "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA=="], - - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], - - "extend-shallow": ["extend-shallow@3.0.2", "", { "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" } }, "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q=="], - - "extglob": ["extglob@2.0.4", "", { "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="], - - "extsprintf": ["extsprintf@1.3.0", "", {}, "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-glob": ["fast-glob@3.1.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.0", "merge2": "^1.3.0", "micromatch": "^4.0.2" } }, "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g=="], - - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - - "fast-url-parser": ["fast-url-parser@1.1.3", "", { "dependencies": { "punycode": "^1.3.2" } }, "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ=="], - - "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="], - - "fastparse": ["fastparse@1.1.2", "", {}, "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="], - - "fastq": ["fastq@1.15.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw=="], - - "fault": ["fault@1.0.4", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA=="], - - "filesize": ["filesize@6.4.0", "", {}, "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ=="], - - "fill-range": ["fill-range@7.0.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ=="], - - "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="], - - "find-cache-dir": ["find-cache-dir@3.3.1", "", { "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" } }, "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ=="], - - "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], - - "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], - - "follow-redirects": ["follow-redirects@1.15.2", "", {}, "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="], - - "for-each": ["for-each@0.3.3", "", { "dependencies": { "is-callable": "^1.1.3" } }, "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw=="], - - "for-in": ["for-in@1.0.2", "", {}, "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="], - - "forever-agent": ["forever-agent@0.6.1", "", {}, "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="], - - "form-data": ["form-data@2.3.3", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ=="], - - "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], - - "fragment-cache": ["fragment-cache@0.2.1", "", { "dependencies": { "map-cache": "^0.2.2" } }, "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA=="], - - "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], - - "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], - - "function-bind": ["function-bind@1.1.1", "", {}, "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="], - - "function.prototype.name": ["function.prototype.name@1.1.5", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "es-abstract": "^1.19.0", "functions-have-names": "^1.2.2" } }, "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA=="], - - "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], - - "generic-names": ["generic-names@2.0.1", "", { "dependencies": { "loader-utils": "^1.1.0" } }, "sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ=="], - - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - - "get-intrinsic": ["get-intrinsic@1.2.0", "", { "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.3" } }, "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q=="], - - "get-orientation": ["get-orientation@1.1.2", "", { "dependencies": { "stream-parser": "^0.3.1" } }, "sha512-/pViTfifW+gBbh/RnlFYHINvELT9Znt+SYyDKAUL6uV6By019AK/s+i9XP4jSwq7lwP38Fd8HVeTxym3+hkwmQ=="], - - "get-port": ["get-port@4.2.0", "", {}, "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw=="], - - "get-symbol-description": ["get-symbol-description@1.0.0", "", { "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" } }, "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw=="], - - "get-value": ["get-value@2.0.6", "", {}, "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="], - - "getpass": ["getpass@0.1.7", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng=="], - - "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], - - "globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], - - "globalthis": ["globalthis@1.0.3", "", { "dependencies": { "define-properties": "^1.1.3" } }, "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA=="], - - "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - - "gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.1.3" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="], - - "graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="], - - "har-schema": ["har-schema@2.0.0", "", {}, "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="], - - "har-validator": ["har-validator@5.1.5", "", { "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w=="], - - "has": ["has@1.0.3", "", { "dependencies": { "function-bind": "^1.1.1" } }, "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw=="], - - "has-ansi": ["has-ansi@2.0.0", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg=="], - - "has-bigints": ["has-bigints@1.0.2", "", {}, "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="], - - "has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - - "has-property-descriptors": ["has-property-descriptors@1.0.0", "", { "dependencies": { "get-intrinsic": "^1.1.1" } }, "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ=="], - - "has-proto": ["has-proto@1.0.1", "", {}, "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="], - - "has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="], - - "has-tostringtag": ["has-tostringtag@1.0.0", "", { "dependencies": { "has-symbols": "^1.0.2" } }, "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ=="], - - "has-value": ["has-value@1.0.0", "", { "dependencies": { "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" } }, "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw=="], - - "has-values": ["has-values@1.0.0", "", { "dependencies": { "is-number": "^3.0.0", "kind-of": "^4.0.0" } }, "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ=="], - - "hash-base": ["hash-base@3.1.0", "", { "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" } }, "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA=="], - - "hash.js": ["hash.js@1.1.7", "", { "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA=="], - - "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - - "hex-color-regex": ["hex-color-regex@1.1.0", "", {}, "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="], - - "highlight.js": ["highlight.js@10.4.1", "", {}, "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg=="], - - "hmac-drbg": ["hmac-drbg@1.0.1", "", { "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg=="], - - "hsl-regex": ["hsl-regex@1.0.0", "", {}, "sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A=="], - - "hsla-regex": ["hsla-regex@1.0.0", "", {}, "sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA=="], - - "html-encoding-sniffer": ["html-encoding-sniffer@1.0.2", "", { "dependencies": { "whatwg-encoding": "^1.0.1" } }, "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw=="], - - "html-tags": ["html-tags@1.2.0", "", {}, "sha512-uVteDXUCs08M7QJx0eY6ue7qQztwIfknap81vAtNob2sdEPKa8PjPinx0vxbs2JONPamovZjMvKZWNW44/PBKg=="], - - "htmlnano": ["htmlnano@0.2.9", "", { "dependencies": { "cssnano": "^4.1.11", "posthtml": "^0.15.1", "purgecss": "^2.3.0", "relateurl": "^0.2.7", "srcset": "^3.0.0", "svgo": "^1.3.2", "terser": "^5.6.1", "timsort": "^0.3.0", "uncss": "^0.17.3" } }, "sha512-jWTtP3dCd7R8x/tt9DK3pvpcQd7HDMcRPUqPxr/i9989q2k5RHIhmlRDFeyQ/LSd8IKrteG8Ce5g0Ig4eGIipg=="], - - "htmlparser2": ["htmlparser2@5.0.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^3.3.0", "domutils": "^2.4.2", "entities": "^2.0.0" } }, "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ=="], - - "http-errors": ["http-errors@1.7.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw=="], - - "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="], - - "http-proxy-middleware": ["http-proxy-middleware@1.3.1", "", { "dependencies": { "@types/http-proxy": "^1.17.5", "http-proxy": "^1.18.1", "is-glob": "^4.0.1", "is-plain-obj": "^3.0.0", "micromatch": "^4.0.2" } }, "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg=="], - - "http-signature": ["http-signature@1.2.0", "", { "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ=="], - - "https-browserify": ["https-browserify@1.0.0", "", {}, "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg=="], - - "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "icss-replace-symbols": ["icss-replace-symbols@1.1.0", "", {}, "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg=="], - - "icss-utils": ["icss-utils@4.1.1", "", { "dependencies": { "postcss": "^7.0.14" } }, "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA=="], - - "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - - "iferr": ["iferr@1.0.2", "", {}, "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg=="], - - "ignore": ["ignore@5.2.4", "", {}, "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ=="], - - "image-size": ["image-size@1.0.0", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw=="], - - "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], - - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "indexes-of": ["indexes-of@1.0.1", "", {}, "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA=="], - - "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "internal-slot": ["internal-slot@1.0.5", "", { "dependencies": { "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" } }, "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ=="], - - "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], - - "is-absolute-url": ["is-absolute-url@3.0.3", "", {}, "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q=="], - - "is-accessor-descriptor": ["is-accessor-descriptor@1.0.0", "", { "dependencies": { "kind-of": "^6.0.0" } }, "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ=="], - - "is-arguments": ["is-arguments@1.1.1", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA=="], - - "is-array-buffer": ["is-array-buffer@3.0.1", "", { "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", "is-typed-array": "^1.1.10" } }, "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ=="], - - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - - "is-bigint": ["is-bigint@1.0.4", "", { "dependencies": { "has-bigints": "^1.0.1" } }, "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg=="], - - "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], - - "is-boolean-object": ["is-boolean-object@1.1.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA=="], - - "is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="], - - "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], - - "is-color-stop": ["is-color-stop@1.1.0", "", { "dependencies": { "css-color-names": "^0.0.4", "hex-color-regex": "^1.1.0", "hsl-regex": "^1.0.0", "hsla-regex": "^1.0.0", "rgb-regex": "^1.0.1", "rgba-regex": "^1.0.0" } }, "sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA=="], - - "is-core-module": ["is-core-module@2.11.0", "", { "dependencies": { "has": "^1.0.3" } }, "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw=="], - - "is-data-descriptor": ["is-data-descriptor@1.0.0", "", { "dependencies": { "kind-of": "^6.0.0" } }, "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ=="], - - "is-date-object": ["is-date-object@1.0.5", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ=="], - - "is-descriptor": ["is-descriptor@1.0.2", "", { "dependencies": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } }, "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg=="], - - "is-directory": ["is-directory@0.3.1", "", {}, "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw=="], - - "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], - - "is-extendable": ["is-extendable@1.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4" } }, "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "is-generator-function": ["is-generator-function@1.0.10", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-html": ["is-html@1.1.0", "", { "dependencies": { "html-tags": "^1.0.0" } }, "sha512-eoGsQVAAyvLFRKnbt4jo7Il56agsH5I04pDymPoxRp/tnna5yiIpdNzvKPOy5G1Ff0zY/jfN2hClb7ju+sOrdA=="], - - "is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], - - "is-nan": ["is-nan@1.3.2", "", { "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" } }, "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w=="], - - "is-negative-zero": ["is-negative-zero@2.0.2", "", {}, "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-number-object": ["is-number-object@1.0.7", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ=="], - - "is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="], - - "is-plain-obj": ["is-plain-obj@3.0.0", "", {}, "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA=="], - - "is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="], - - "is-regex": ["is-regex@1.1.4", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg=="], - - "is-resolvable": ["is-resolvable@1.1.0", "", {}, "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg=="], - - "is-shared-array-buffer": ["is-shared-array-buffer@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2" } }, "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA=="], - - "is-string": ["is-string@1.0.7", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg=="], - - "is-symbol": ["is-symbol@1.0.4", "", { "dependencies": { "has-symbols": "^1.0.2" } }, "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg=="], - - "is-typed-array": ["is-typed-array@1.1.10", "", { "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" } }, "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A=="], - - "is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="], - - "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], - - "is-url": ["is-url@1.2.4", "", {}, "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="], - - "is-weakref": ["is-weakref@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2" } }, "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ=="], - - "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], - - "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - - "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "isobject": ["isobject@3.0.1", "", {}, "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="], - - "isstream": ["isstream@0.1.2", "", {}, "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="], - - "jest-worker": ["jest-worker@27.0.0-next.5", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-mk0umAQ5lT+CaOJ+Qp01N6kz48sJG2kr2n1rX0koqKf6FIygQV0qLOdN9SCYID4IVeSigDOcPeGLozdMLYfb5g=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], - - "jsbn": ["jsbn@0.1.1", "", {}, "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="], - - "jsdom": ["jsdom@14.1.0", "", { "dependencies": { "abab": "^2.0.0", "acorn": "^6.0.4", "acorn-globals": "^4.3.0", "array-equal": "^1.0.0", "cssom": "^0.3.4", "cssstyle": "^1.1.1", "data-urls": "^1.1.0", "domexception": "^1.0.1", "escodegen": "^1.11.0", "html-encoding-sniffer": "^1.0.2", "nwsapi": "^2.1.3", "parse5": "5.1.0", "pn": "^1.1.0", "request": "^2.88.0", "request-promise-native": "^1.0.5", "saxes": "^3.1.9", "symbol-tree": "^3.2.2", "tough-cookie": "^2.5.0", "w3c-hr-time": "^1.0.1", "w3c-xmlserializer": "^1.1.2", "webidl-conversions": "^4.0.2", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^7.0.0", "ws": "^6.1.2", "xml-name-validator": "^3.0.0" } }, "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng=="], - - "jsesc": ["jsesc@2.5.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="], - - "json-parse-better-errors": ["json-parse-better-errors@1.0.2", "", {}, "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="], - - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], - - "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], - - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "json-source-map": ["json-source-map@0.6.1", "", {}, "sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg=="], - - "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], - - "json2mq": ["json2mq@0.2.0", "", { "dependencies": { "string-convert": "^0.2.0" } }, "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA=="], - - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - - "jsprim": ["jsprim@1.4.2", "", { "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw=="], - - "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], - - "left-pad": ["left-pad@1.3.0", "", {}, "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA=="], - - "levn": ["levn@0.3.0", "", { "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" } }, "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA=="], - - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - - "loader-utils": ["loader-utils@1.2.3", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^2.0.0", "json5": "^1.0.1" } }, "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA=="], - - "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], - - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], - - "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], - - "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], - - "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="], - - "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], - - "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], - - "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - - "lowlight": ["lowlight@1.17.0", "", { "dependencies": { "fault": "^1.0.0", "highlight.js": "~10.4.0" } }, "sha512-vmtBgYKD+QVNy7tIa7ulz5d//Il9R4MooOVh4nkOf9R9Cb/Dk5TXMSTieg/vDulkBkIWj59/BIlyFQxT9X1oAQ=="], - - "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - - "make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], - - "map-cache": ["map-cache@0.2.2", "", {}, "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="], - - "map-visit": ["map-visit@1.0.0", "", { "dependencies": { "object-visit": "^1.0.0" } }, "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w=="], - - "md5.js": ["md5.js@1.3.5", "", { "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg=="], - - "mdn-data": ["mdn-data@2.0.4", "", {}, "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="], - - "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], - - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "micromatch": ["micromatch@4.0.5", "", { "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" } }, "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA=="], - - "miller-rabin": ["miller-rabin@4.0.1", "", { "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" }, "bin": { "miller-rabin": "bin/miller-rabin" } }, "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA=="], - - "mime-db": ["mime-db@1.33.0", "", {}, "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="], - - "mime-types": ["mime-types@2.1.18", "", { "dependencies": { "mime-db": "~1.33.0" } }, "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ=="], - - "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], - - "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="], - - "minimalistic-crypto-utils": ["minimalistic-crypto-utils@1.0.1", "", {}, "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="], - - "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "mixin-deep": ["mixin-deep@1.3.2", "", { "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" } }, "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA=="], - - "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], - - "moment": ["moment@2.29.4", "", {}, "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="], - - "ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], - - "nanoid": ["nanoid@3.3.4", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="], - - "nanomatch": ["nanomatch@1.2.13", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "fragment-cache": "^0.2.1", "is-windows": "^1.0.2", "kind-of": "^6.0.2", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA=="], - - "native-url": ["native-url@0.3.4", "", { "dependencies": { "querystring": "^0.2.0" } }, "sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA=="], - - "ncp": ["ncp@2.0.0", "", { "bin": { "ncp": "./bin/ncp" } }, "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA=="], - - "next": ["next@11.1.4", "", { "dependencies": { "@babel/runtime": "7.15.3", "@hapi/accept": "5.0.2", "@next/env": "11.1.4", "@next/polyfill-module": "11.1.4", "@next/react-dev-overlay": "11.1.4", "@next/react-refresh-utils": "11.1.4", "@next/swc-darwin-arm64": "11.1.4", "@next/swc-darwin-x64": "11.1.4", "@next/swc-linux-x64-gnu": "11.1.4", "@next/swc-win32-x64-msvc": "11.1.4", "@node-rs/helper": "1.2.1", "assert": "2.0.0", "ast-types": "0.13.2", "browserify-zlib": "0.2.0", "browserslist": "4.16.6", "buffer": "5.6.0", "caniuse-lite": "^1.0.30001228", "chalk": "2.4.2", "chokidar": "3.5.1", "constants-browserify": "1.0.0", "crypto-browserify": "3.12.0", "cssnano-simple": "3.0.0", "domain-browser": "4.19.0", "encoding": "0.1.13", "etag": "1.8.1", "find-cache-dir": "3.3.1", "get-orientation": "1.1.2", "https-browserify": "1.0.0", "image-size": "1.0.0", "jest-worker": "27.0.0-next.5", "native-url": "0.3.4", "node-fetch": "2.6.7", "node-html-parser": "1.4.9", "node-libs-browser": "^2.2.1", "os-browserify": "0.3.0", "p-limit": "3.1.0", "path-browserify": "1.0.1", "pnp-webpack-plugin": "1.6.4", "postcss": "8.2.15", "process": "0.11.10", "querystring-es3": "0.2.1", "raw-body": "2.4.1", "react-is": "17.0.2", "react-refresh": "0.8.3", "stream-browserify": "3.0.0", "stream-http": "3.1.1", "string_decoder": "1.3.0", "styled-jsx": "4.0.1", "timers-browserify": "2.0.12", "tty-browserify": "0.0.1", "use-subscription": "1.5.1", "util": "0.12.4", "vm-browserify": "1.1.2", "watchpack": "2.1.1" }, "peerDependencies": { "fibers": ">= 3.1.0", "node-sass": "^4.0.0 || ^5.0.0", "react": "^17.0.2", "react-dom": "^17.0.2", "sass": "^1.3.0" }, "optionalPeers": ["fibers", "node-sass", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-GWQJrWYkfAKP8vmrzJcCfRSKv955Khyjqd5jipTcVKDGg+SH+NfjDMWFtCwArcQlHPvzisGu1ERLY0+Eoj7G+g=="], - - "nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], - - "node-addon-api": ["node-addon-api@3.2.1", "", {}, "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A=="], - - "node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" } }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="], - - "node-forge": ["node-forge@0.10.0", "", {}, "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="], - - "node-gyp-build": ["node-gyp-build@4.6.0", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ=="], - - "node-html-parser": ["node-html-parser@1.4.9", "", { "dependencies": { "he": "1.2.0" } }, "sha512-UVcirFD1Bn0O+TSmloHeHqZZCxHjvtIeGdVdGMhyZ8/PWlEiZaZ5iJzR189yKZr8p0FXN58BUeC7RHRkf/KYGw=="], - - "node-libs-browser": ["node-libs-browser@2.2.1", "", { "dependencies": { "assert": "^1.1.1", "browserify-zlib": "^0.2.0", "buffer": "^4.3.0", "console-browserify": "^1.1.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", "readable-stream": "^2.3.3", "stream-browserify": "^2.0.1", "stream-http": "^2.7.2", "string_decoder": "^1.0.0", "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.11.0", "vm-browserify": "^1.0.1" } }, "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q=="], - - "node-releases": ["node-releases@1.1.77", "", {}, "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ=="], - - "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - - "normalize-url": ["normalize-url@3.3.0", "", {}, "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg=="], - - "nth-check": ["nth-check@1.0.2", "", { "dependencies": { "boolbase": "~1.0.0" } }, "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg=="], - - "nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="], - - "nwsapi": ["nwsapi@2.2.2", "", {}, "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw=="], - - "oauth-sign": ["oauth-sign@0.9.0", "", {}, "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="], - - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "object-copy": ["object-copy@0.1.0", "", { "dependencies": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" } }, "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ=="], - - "object-inspect": ["object-inspect@1.12.3", "", {}, "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g=="], - - "object-is": ["object-is@1.1.5", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw=="], - - "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], - - "object-visit": ["object-visit@1.0.1", "", { "dependencies": { "isobject": "^3.0.0" } }, "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA=="], - - "object.assign": ["object.assign@4.1.4", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ=="], - - "object.getownpropertydescriptors": ["object.getownpropertydescriptors@2.1.5", "", { "dependencies": { "array.prototype.reduce": "^1.0.5", "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.20.4" } }, "sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw=="], - - "object.pick": ["object.pick@1.3.0", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ=="], - - "object.values": ["object.values@1.1.6", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.20.4" } }, "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw=="], - - "on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="], - - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], - - "open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], - - "optionator": ["optionator@0.8.3", "", { "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "word-wrap": "~1.2.3" } }, "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA=="], - - "ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], - - "os-browserify": ["os-browserify@0.3.0", "", {}, "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A=="], - - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - - "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - - "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], - - "pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - - "parcel": ["parcel@2.0.0-beta.3", "", { "dependencies": { "@parcel/config-default": "2.0.0-beta.3", "@parcel/core": "2.0.0-beta.3", "@parcel/diagnostic": "2.0.0-beta.3", "@parcel/events": "2.0.0-beta.3", "@parcel/fs": "2.0.0-beta.3", "@parcel/logger": "2.0.0-beta.3", "@parcel/package-manager": "2.0.0-beta.3", "@parcel/reporter-cli": "2.0.0-beta.3", "@parcel/reporter-dev-server": "2.0.0-beta.3", "@parcel/utils": "2.0.0-beta.3", "chalk": "^4.1.0", "commander": "^7.0.0", "get-port": "^4.2.0", "v8-compile-cache": "^2.0.0" }, "bin": { "parcel": "lib/bin.js" } }, "sha512-85lYzs87O7jedNhuKj21fqA4Kq0dDXFHNOqxvKnIxltlPLXPXFiGwR2EcjTmF8Trv82KoeKWuWLtUVSzjZ79nQ=="], - - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "parse-asn1": ["parse-asn1@5.1.6", "", { "dependencies": { "asn1.js": "^5.2.0", "browserify-aes": "^1.0.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" } }, "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw=="], - - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], - - "parse5": ["parse5@5.1.0", "", {}, "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ=="], - - "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - - "pascalcase": ["pascalcase@0.1.1", "", {}, "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="], - - "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - - "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], - - "path-is-inside": ["path-is-inside@1.0.2", "", {}, "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w=="], - - "path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - - "path-to-regexp": ["path-to-regexp@2.2.1", "", {}, "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ=="], - - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - - "pbkdf2": ["pbkdf2@3.1.2", "", { "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", "ripemd160": "^2.0.1", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" } }, "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA=="], - - "performance-now": ["performance-now@2.1.0", "", {}, "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="], - - "picocolors": ["picocolors@1.0.0", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="], - - "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - - "pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="], - - "platform": ["platform@1.3.6", "", {}, "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="], - - "pn": ["pn@1.1.0", "", {}, "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA=="], - - "pnp-webpack-plugin": ["pnp-webpack-plugin@1.6.4", "", { "dependencies": { "ts-pnp": "^1.1.6" } }, "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg=="], - - "posix-character-classes": ["posix-character-classes@0.1.1", "", {}, "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="], - - "postcss": ["postcss@8.2.15", "", { "dependencies": { "colorette": "^1.2.2", "nanoid": "^3.1.23", "source-map": "^0.6.1" } }, "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q=="], - - "postcss-calc": ["postcss-calc@7.0.5", "", { "dependencies": { "postcss": "^7.0.27", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.0.2" } }, "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg=="], - - "postcss-colormin": ["postcss-colormin@4.0.3", "", { "dependencies": { "browserslist": "^4.0.0", "color": "^3.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw=="], - - "postcss-convert-values": ["postcss-convert-values@4.0.1", "", { "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ=="], - - "postcss-discard-comments": ["postcss-discard-comments@4.0.2", "", { "dependencies": { "postcss": "^7.0.0" } }, "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg=="], - - "postcss-discard-duplicates": ["postcss-discard-duplicates@4.0.2", "", { "dependencies": { "postcss": "^7.0.0" } }, "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ=="], - - "postcss-discard-empty": ["postcss-discard-empty@4.0.1", "", { "dependencies": { "postcss": "^7.0.0" } }, "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w=="], - - "postcss-discard-overridden": ["postcss-discard-overridden@4.0.1", "", { "dependencies": { "postcss": "^7.0.0" } }, "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg=="], - - "postcss-merge-longhand": ["postcss-merge-longhand@4.0.11", "", { "dependencies": { "css-color-names": "0.0.4", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "stylehacks": "^4.0.0" } }, "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw=="], - - "postcss-merge-rules": ["postcss-merge-rules@4.0.3", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-api": "^3.0.0", "cssnano-util-same-parent": "^4.0.0", "postcss": "^7.0.0", "postcss-selector-parser": "^3.0.0", "vendors": "^1.0.0" } }, "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ=="], - - "postcss-minify-font-values": ["postcss-minify-font-values@4.0.2", "", { "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg=="], - - "postcss-minify-gradients": ["postcss-minify-gradients@4.0.2", "", { "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "is-color-stop": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q=="], - - "postcss-minify-params": ["postcss-minify-params@4.0.2", "", { "dependencies": { "alphanum-sort": "^1.0.0", "browserslist": "^4.0.0", "cssnano-util-get-arguments": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "uniqs": "^2.0.0" } }, "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg=="], - - "postcss-minify-selectors": ["postcss-minify-selectors@4.0.2", "", { "dependencies": { "alphanum-sort": "^1.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-selector-parser": "^3.0.0" } }, "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g=="], - - "postcss-modules": ["postcss-modules@3.2.2", "", { "dependencies": { "generic-names": "^2.0.1", "icss-replace-symbols": "^1.1.0", "lodash.camelcase": "^4.3.0", "postcss": "^7.0.32", "postcss-modules-extract-imports": "^2.0.0", "postcss-modules-local-by-default": "^3.0.2", "postcss-modules-scope": "^2.2.0", "postcss-modules-values": "^3.0.0", "string-hash": "^1.1.1" } }, "sha512-JQ8IAqHELxC0N6tyCg2UF40pACY5oiL6UpiqqcIFRWqgDYO8B0jnxzoQ0EOpPrWXvcpu6BSbQU/3vSiq7w8Nhw=="], - - "postcss-modules-extract-imports": ["postcss-modules-extract-imports@1.1.0", "", { "dependencies": { "postcss": "^6.0.1" } }, "sha512-zF9+UIEvtpeqMGxhpeT9XaIevQSrBBCz9fi7SwfkmjVacsSj8DY5eFVgn+wY8I9vvdDDwK5xC8Myq4UkoLFIkA=="], - - "postcss-modules-local-by-default": ["postcss-modules-local-by-default@1.2.0", "", { "dependencies": { "css-selector-tokenizer": "^0.7.0", "postcss": "^6.0.1" } }, "sha512-X4cquUPIaAd86raVrBwO8fwRfkIdbwFu7CTfEOjiZQHVQwlHRSkTgH5NLDmMm5+1hQO8u6dZ+TOOJDbay1hYpA=="], - - "postcss-modules-scope": ["postcss-modules-scope@1.1.0", "", { "dependencies": { "css-selector-tokenizer": "^0.7.0", "postcss": "^6.0.1" } }, "sha512-LTYwnA4C1He1BKZXIx1CYiHixdSe9LWYVKadq9lK5aCCMkoOkFyZ7aigt+srfjlRplJY3gIol6KUNefdMQJdlw=="], - - "postcss-modules-values": ["postcss-modules-values@1.3.0", "", { "dependencies": { "icss-replace-symbols": "^1.1.0", "postcss": "^6.0.1" } }, "sha512-i7IFaR9hlQ6/0UgFuqM6YWaCfA1Ej8WMg8A5DggnH1UGKJvTV/ugqq/KaULixzzOi3T/tF6ClBXcHGCzdd5unA=="], - - "postcss-normalize-charset": ["postcss-normalize-charset@4.0.1", "", { "dependencies": { "postcss": "^7.0.0" } }, "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g=="], - - "postcss-normalize-display-values": ["postcss-normalize-display-values@4.0.2", "", { "dependencies": { "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ=="], - - "postcss-normalize-positions": ["postcss-normalize-positions@4.0.2", "", { "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA=="], - - "postcss-normalize-repeat-style": ["postcss-normalize-repeat-style@4.0.2", "", { "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q=="], - - "postcss-normalize-string": ["postcss-normalize-string@4.0.2", "", { "dependencies": { "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA=="], - - "postcss-normalize-timing-functions": ["postcss-normalize-timing-functions@4.0.2", "", { "dependencies": { "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A=="], - - "postcss-normalize-unicode": ["postcss-normalize-unicode@4.0.1", "", { "dependencies": { "browserslist": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg=="], - - "postcss-normalize-url": ["postcss-normalize-url@4.0.1", "", { "dependencies": { "is-absolute-url": "^2.0.0", "normalize-url": "^3.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA=="], - - "postcss-normalize-whitespace": ["postcss-normalize-whitespace@4.0.2", "", { "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA=="], - - "postcss-ordered-values": ["postcss-ordered-values@4.1.2", "", { "dependencies": { "cssnano-util-get-arguments": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw=="], - - "postcss-reduce-initial": ["postcss-reduce-initial@4.0.3", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-api": "^3.0.0", "has": "^1.0.0", "postcss": "^7.0.0" } }, "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA=="], - - "postcss-reduce-transforms": ["postcss-reduce-transforms@4.0.2", "", { "dependencies": { "cssnano-util-get-match": "^4.0.0", "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" } }, "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg=="], - - "postcss-selector-parser": ["postcss-selector-parser@6.0.11", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g=="], - - "postcss-svgo": ["postcss-svgo@4.0.3", "", { "dependencies": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "svgo": "^1.0.0" } }, "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw=="], - - "postcss-unique-selectors": ["postcss-unique-selectors@4.0.1", "", { "dependencies": { "alphanum-sort": "^1.0.0", "postcss": "^7.0.0", "uniqs": "^2.0.0" } }, "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg=="], - - "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], - - "posthtml": ["posthtml@0.15.2", "", { "dependencies": { "posthtml-parser": "^0.7.2", "posthtml-render": "^1.3.1" } }, "sha512-YugEJ5ze/0DLRIVBjCpDwANWL4pPj1kHJ/2llY8xuInr0nbkon3qTiMPe5LQa+cCwNjxS7nAZZTp+1M+6mT4Zg=="], - - "posthtml-parser": ["posthtml-parser@0.6.0", "", { "dependencies": { "htmlparser2": "^5.0.1" } }, "sha512-5ffwKQNgtVHdhZniWxu+1ryvaZv5l25HPLUV6W5xy5nYVWMXtvjtwRnbSpfbKFvbyl7XI+d4AqkjmonkREqnXA=="], - - "posthtml-render": ["posthtml-render@1.4.0", "", {}, "sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw=="], - - "prelude-ls": ["prelude-ls@1.1.2", "", {}, "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w=="], - - "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], - - "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], - - "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], - - "prop-types-extra": ["prop-types-extra@1.1.1", "", { "dependencies": { "react-is": "^16.3.2", "warning": "^4.0.0" }, "peerDependencies": { "react": ">=0.14.0" } }, "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew=="], - - "psl": ["psl@1.9.0", "", {}, "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="], - - "public-encrypt": ["public-encrypt@4.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q=="], - - "punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="], - - "purgecss": ["purgecss@2.3.0", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.0.0", "postcss": "7.0.32", "postcss-selector-parser": "^6.0.2" }, "bin": { "purgecss": "bin/purgecss" } }, "sha512-BE5CROfVGsx2XIhxGuZAT7rTH9lLeQx/6M0P7DTXQH4IUc3BBzs9JUzt4yzGf3JrH9enkeq6YJBe9CTtkm1WmQ=="], - - "q": ["q@1.5.1", "", {}, "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw=="], - - "qs": ["qs@6.5.3", "", {}, "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="], - - "querystring": ["querystring@0.2.1", "", {}, "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg=="], - - "querystring-es3": ["querystring-es3@0.2.1", "", {}, "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA=="], - - "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="], - - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="], - - "randomfill": ["randomfill@1.0.4", "", { "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw=="], - - "range-parser": ["range-parser@1.2.0", "", {}, "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A=="], - - "raw-body": ["raw-body@2.4.1", "", { "dependencies": { "bytes": "3.1.0", "http-errors": "1.7.3", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA=="], - - "rc-align": ["rc-align@4.0.15", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "dom-align": "^1.7.0", "rc-util": "^5.26.0", "resize-observer-polyfill": "^1.5.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA=="], - - "rc-cascader": ["rc-cascader@3.7.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "array-tree-filter": "^2.1.0", "classnames": "^2.3.1", "rc-select": "~14.1.0", "rc-tree": "~5.7.0", "rc-util": "^5.6.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A=="], - - "rc-checkbox": ["rc-checkbox@2.3.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg=="], - - "rc-collapse": ["rc-collapse@3.4.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-motion": "^2.3.4", "rc-util": "^5.2.1", "shallowequal": "^1.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-jpTwLgJzkhAgp2Wpi3xmbTbbYExg6fkptL67Uu5LCRVEj6wqmy0DHTjjeynsjOLsppHGHu41t1ELntZ0lEvS/Q=="], - - "rc-dialog": ["rc-dialog@9.0.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/portal": "^1.0.0-8", "classnames": "^2.2.6", "rc-motion": "^2.3.0", "rc-util": "^5.21.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-s3U+24xWUuB6Bn2Lk/Qt6rufy+uT+QvWkiFhNBcO9APLxcFFczWamaq7x9h8SCuhfc1nHcW4y8NbMsnAjNnWyg=="], - - "rc-drawer": ["rc-drawer@6.1.3", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/portal": "^1.0.0-6", "classnames": "^2.2.6", "rc-motion": "^2.6.1", "rc-util": "^5.21.2" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-AvHisO90A+xMLMKBw2zs89HxjWxusM2BUABlgK60RhweIHF8W/wk0hSOrxBlUXoA9r1F+10na3g6GZ97y1qDZA=="], - - "rc-dropdown": ["rc-dropdown@4.0.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "classnames": "^2.2.6", "rc-trigger": "^5.3.1", "rc-util": "^5.17.0" }, "peerDependencies": { "react": ">=16.11.0", "react-dom": ">=16.11.0" } }, "sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g=="], - - "rc-field-form": ["rc-field-form@1.27.4", "", { "dependencies": { "@babel/runtime": "^7.18.0", "async-validator": "^4.1.0", "rc-util": "^5.8.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-PQColQnZimGKArnOh8V2907+VzDCXcqtFvHgevDLtqWc/P7YASb/FqntSmdS8q3VND5SHX3Y1vgMIzY22/f/0Q=="], - - "rc-image": ["rc-image@5.13.0", "", { "dependencies": { "@babel/runtime": "^7.11.2", "@rc-component/portal": "^1.0.2", "classnames": "^2.2.6", "rc-dialog": "~9.0.0", "rc-motion": "^2.6.2", "rc-util": "^5.0.6" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-iZTOmw5eWo2+gcrJMMcnd7SsxVHl3w5xlyCgsULUdJhJbnuI8i/AL0tVOsE7aLn9VfOh1qgDT3mC2G75/c7mqg=="], - - "rc-input": ["rc-input@0.1.4", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-util": "^5.18.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-FqDdNz+fV2dKNgfXzcSLKvC+jEs1709t7nD+WdfjrdSaOcefpgc7BUJYadc3usaING+b7ediMTfKxuJBsEFbXA=="], - - "rc-input-number": ["rc-input-number@7.3.11", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", "rc-util": "^5.23.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-aMWPEjFeles6PQnMqP5eWpxzsvHm9rh1jQOWXExUEIxhX62Fyl/ptifLHOn17+waDG1T/YUb6flfJbvwRhHrbA=="], - - "rc-mentions": ["rc-mentions@1.13.1", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", "rc-menu": "~9.8.0", "rc-textarea": "^0.4.0", "rc-trigger": "^5.0.4", "rc-util": "^5.22.5" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw=="], - - "rc-menu": ["rc-menu@9.8.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-motion": "^2.4.3", "rc-overflow": "^1.2.8", "rc-trigger": "^5.1.2", "rc-util": "^5.27.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-EahOJVjLuEnJsThoPN+mGnVm431RzVzDLZWHRS/YnXTQULa7OsgdJa/Y7qXxc3Z5sz8mgT6xYtgpmBXLxrZFaQ=="], - - "rc-motion": ["rc-motion@2.6.3", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-util": "^5.21.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-xFLkes3/7VL/J+ah9jJruEW/Akbx5F6jVa2wG5o/ApGKQKSOd5FR3rseHLL9+xtJg4PmCwo6/1tqhDO/T+jFHA=="], - - "rc-notification": ["rc-notification@4.6.1", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-motion": "^2.2.0", "rc-util": "^5.20.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-NSmFYwrrdY3+un1GvDAJQw62Xi9LNMSsoQyo95tuaYrcad5Bn9gJUL8AREufRxSQAQnr64u3LtP3EUyLYT6bhw=="], - - "rc-overflow": ["rc-overflow@1.2.8", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-resize-observer": "^1.0.0", "rc-util": "^5.19.2" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ=="], - - "rc-pagination": ["rc-pagination@3.2.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-5tIXjB670WwwcAJzAqp2J+cOBS9W3cH/WU1EiYwXljuZ4vtZXKlY2Idq8FZrnYBz8KhN3vwPo9CoV/SJS6SL1w=="], - - "rc-picker": ["rc-picker@2.7.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", "date-fns": "2.x", "dayjs": "1.x", "moment": "^2.24.0", "rc-trigger": "^5.0.4", "rc-util": "^5.4.0", "shallowequal": "^1.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-oZH6FZ3j4iuBxHB4NvQ6ABRsS2If/Kpty1YFFsji7/aej6ruGmfM7WnJWQ88AoPfpJ++ya5z+nVEA8yCRYGKyw=="], - - "rc-progress": ["rc-progress@3.4.1", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", "rc-util": "^5.16.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-eAFDHXlk8aWpoXl0llrenPMt9qKHQXphxcVsnKs0FHC6eCSk1ebJtyaVjJUzKe0233ogiLDeEFK1Uihz3s67hw=="], - - "rc-rate": ["rc-rate@2.9.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", "rc-util": "^5.0.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g=="], - - "rc-resize-observer": ["rc-resize-observer@1.3.1", "", { "dependencies": { "@babel/runtime": "^7.20.7", "classnames": "^2.2.1", "rc-util": "^5.27.0", "resize-observer-polyfill": "^1.5.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg=="], - - "rc-segmented": ["rc-segmented@2.1.2", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-motion": "^2.4.4", "rc-util": "^5.17.0" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-qGo1bCr83ESXpXVOCXjFe1QJlCAQXyi9KCiy8eX3rIMYlTeJr/ftySIaTnYsitL18SvWf5ZEHsfqIWoX0EMfFQ=="], - - "rc-select": ["rc-select@14.1.16", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-motion": "^2.0.1", "rc-overflow": "^1.0.0", "rc-trigger": "^5.0.4", "rc-util": "^5.16.1", "rc-virtual-list": "^3.2.0" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-71XLHleuZmufpdV2vis5oituRkhg2WNvLpVMJBGWRar6WGAVOHXaY9DR5HvwWry3EGTn19BqnL6Xbybje6f8YA=="], - - "rc-slider": ["rc-slider@10.0.1", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", "rc-util": "^5.18.1", "shallowequal": "^1.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q=="], - - "rc-steps": ["rc-steps@5.0.0-alpha.2", "", { "dependencies": { "@babel/runtime": "^7.16.7", "classnames": "^2.2.3", "rc-util": "^5.16.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-WPH5jgLnQ1OJHs5SnSp46Ep0wqK0afT1+6MVc4sU9uD+7W1v6Ccisrz0v1ZCsTmQJVwiD7mwVaZ+l75iMHcrvg=="], - - "rc-switch": ["rc-switch@3.2.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", "rc-util": "^5.0.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A=="], - - "rc-table": ["rc-table@7.26.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", "rc-resize-observer": "^1.1.0", "rc-util": "^5.22.5", "shallowequal": "^1.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ=="], - - "rc-tabs": ["rc-tabs@12.5.6", "", { "dependencies": { "@babel/runtime": "^7.11.2", "classnames": "2.x", "rc-dropdown": "~4.0.0", "rc-menu": "~9.8.0", "rc-motion": "^2.6.2", "rc-resize-observer": "^1.0.0", "rc-util": "^5.16.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-aArXHzxK7YICxe+622CZ8FlO5coMi8P7E6tXpseCPKm1gdTjUt0LrQK1/AxcrRXZXG3K4QqhlKmET0+cX5DQaQ=="], - - "rc-textarea": ["rc-textarea@0.4.7", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", "rc-resize-observer": "^1.0.0", "rc-util": "^5.24.4", "shallowequal": "^1.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-IQPd1CDI3mnMlkFyzt2O4gQ2lxUsnBAeJEoZGJnkkXgORNqyM9qovdrCj9NzcRfpHgLdzaEbU3AmobNFGUznwQ=="], - - "rc-tooltip": ["rc-tooltip@5.2.2", "", { "dependencies": { "@babel/runtime": "^7.11.2", "classnames": "^2.3.1", "rc-trigger": "^5.0.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg=="], - - "rc-tree": ["rc-tree@5.7.2", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-motion": "^2.0.1", "rc-util": "^5.16.1", "rc-virtual-list": "^3.4.8" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-nmnL6qLnfwVckO5zoqKL2I9UhwDqzyCtjITQCkwhimyz1zfuFkG5ZPIXpzD/Guzso94qQA/QrMsvzic5W6QDjg=="], - - "rc-tree-select": ["rc-tree-select@5.5.5", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-select": "~14.1.0", "rc-tree": "~5.7.0", "rc-util": "^5.16.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw=="], - - "rc-trigger": ["rc-trigger@5.3.4", "", { "dependencies": { "@babel/runtime": "^7.18.3", "classnames": "^2.2.6", "rc-align": "^4.0.0", "rc-motion": "^2.0.0", "rc-util": "^5.19.2" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw=="], - - "rc-upload": ["rc-upload@4.3.4", "", { "dependencies": { "@babel/runtime": "^7.18.3", "classnames": "^2.2.5", "rc-util": "^5.2.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ=="], - - "rc-util": ["rc-util@5.27.2", "", { "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^16.12.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-8XHRbeJOWlTR2Hk1K2xLaPOf7lZu+3taskAGuqOPccA676vB3ygrz3ZgdrA3wml40CzR9RlIEHDWwI7FZT3wBQ=="], - - "rc-virtual-list": ["rc-virtual-list@3.4.13", "", { "dependencies": { "@babel/runtime": "^7.20.0", "classnames": "^2.2.6", "rc-resize-observer": "^1.0.0", "rc-util": "^5.15.0" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-cPOVDmcNM7rH6ANotanMDilW/55XnFPw0Jh/GQYtrzZSy3AmWvCnqVNyNC/pgg3lfVmX2994dlzAhuUrd4jG7w=="], - - "react": ["react@17.0.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="], - - "react-bootstrap": ["react-bootstrap@1.6.6", "", { "dependencies": { "@babel/runtime": "^7.14.0", "@restart/context": "^2.1.4", "@restart/hooks": "^0.4.7", "@types/invariant": "^2.2.33", "@types/prop-types": "^15.7.3", "@types/react": ">=16.14.8", "@types/react-transition-group": "^4.4.1", "@types/warning": "^3.0.0", "classnames": "^2.3.1", "dom-helpers": "^5.2.1", "invariant": "^2.2.4", "prop-types": "^15.7.2", "prop-types-extra": "^1.1.0", "react-overlays": "^5.1.2", "react-transition-group": "^4.4.1", "uncontrollable": "^7.2.1", "warning": "^4.0.3" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-pSzYyJT5u4rc8+5myM8Vid2JG52L8AmYSkpznReH/GM4+FhLqEnxUa0+6HRTaGwjdEixQNGchwY+b3xCdYWrDA=="], - - "react-dom": ["react-dom@17.0.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "scheduler": "^0.20.2" }, "peerDependencies": { "react": "17.0.2" } }, "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA=="], - - "react-form": ["react-form@4.0.1", "", { "peerDependencies": { "prop-types": "^15.5.4", "react": "^16.8.3" } }, "sha512-vhsCuBLZJYjm6vd8TBxIhIWeB/8Jg4mmmiR3Zj+1zIGBM39qJf1CLqekadLp0J9NeW0EsZxUnBtbmEnMeZ/7Pw=="], - - "react-hook-form": ["react-hook-form@7.43.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18" } }, "sha512-+s3+s8LLytRMriwwuSqeLStVjRXFGxgjjx2jED7Z+wz1J/88vpxieRQGvJVvzrzVxshZ0BRuocFERb779m2kNg=="], - - "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], - - "react-lifecycles-compat": ["react-lifecycles-compat@3.0.4", "", {}, "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="], - - "react-overlays": ["react-overlays@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.13.8", "@popperjs/core": "^2.11.6", "@restart/hooks": "^0.4.7", "@types/warning": "^3.0.0", "dom-helpers": "^5.2.0", "prop-types": "^15.7.2", "uncontrollable": "^7.2.1", "warning": "^4.0.3" }, "peerDependencies": { "react": ">=16.3.0", "react-dom": ">=16.3.0" } }, "sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA=="], - - "react-refresh": ["react-refresh@0.9.0", "", {}, "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ=="], - - "react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="], - - "readable-stream": ["readable-stream@2.3.7", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw=="], - - "readdirp": ["readdirp@3.5.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ=="], - - "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="], - - "regex-not": ["regex-not@1.0.2", "", { "dependencies": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" } }, "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A=="], - - "regexp.prototype.flags": ["regexp.prototype.flags@1.4.3", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "functions-have-names": "^1.2.2" } }, "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA=="], - - "relateurl": ["relateurl@0.2.7", "", {}, "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog=="], - - "repeat-element": ["repeat-element@1.1.4", "", {}, "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ=="], - - "repeat-string": ["repeat-string@1.6.1", "", {}, "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="], - - "request": ["request@2.88.2", "", { "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" } }, "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw=="], - - "request-promise-core": ["request-promise-core@1.1.4", "", { "dependencies": { "lodash": "^4.17.19" }, "peerDependencies": { "request": "^2.34" } }, "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw=="], - - "request-promise-native": ["request-promise-native@1.0.9", "", { "dependencies": { "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" }, "peerDependencies": { "request": "^2.34" } }, "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g=="], - - "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="], - - "resize-observer-polyfill": ["resize-observer-polyfill@1.5.1", "", {}, "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="], - - "resolve": ["resolve@1.22.1", "", { "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw=="], - - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - - "resolve-url": ["resolve-url@0.2.1", "", {}, "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg=="], - - "restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], - - "ret": ["ret@0.1.15", "", {}, "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="], - - "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], - - "rgb-regex": ["rgb-regex@1.0.1", "", {}, "sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w=="], - - "rgba-regex": ["rgba-regex@1.0.0", "", {}, "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg=="], - - "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - - "ripemd160": ["ripemd160@2.0.2", "", { "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" } }, "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - - "safe-regex": ["safe-regex@1.1.0", "", { "dependencies": { "ret": "~0.1.10" } }, "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg=="], - - "safe-regex-test": ["safe-regex-test@1.0.0", "", { "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", "is-regex": "^1.1.4" } }, "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA=="], - - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - - "sax": ["sax@1.2.4", "", {}, "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="], - - "saxes": ["saxes@3.1.11", "", { "dependencies": { "xmlchars": "^2.1.1" } }, "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g=="], - - "scheduler": ["scheduler@0.20.2", "", { "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ=="], - - "scroll-into-view-if-needed": ["scroll-into-view-if-needed@2.2.31", "", { "dependencies": { "compute-scroll-into-view": "^1.0.20" } }, "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA=="], - - "semver": ["semver@6.3.0", "", { "bin": { "semver": "./bin/semver.js" } }, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="], - - "serve-handler": ["serve-handler@6.1.5", "", { "dependencies": { "bytes": "3.0.0", "content-disposition": "0.5.2", "fast-url-parser": "1.1.3", "mime-types": "2.1.18", "minimatch": "3.1.2", "path-is-inside": "1.0.2", "path-to-regexp": "2.2.1", "range-parser": "1.2.0" } }, "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg=="], - - "set-value": ["set-value@2.0.1", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" } }, "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw=="], - - "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="], - - "setprototypeof": ["setprototypeof@1.1.1", "", {}, "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="], - - "sha.js": ["sha.js@2.4.11", "", { "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" }, "bin": { "sha.js": "./bin.js" } }, "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ=="], - - "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="], - - "shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], - - "shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - - "shell-quote": ["shell-quote@1.7.2", "", {}, "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg=="], - - "side-channel": ["side-channel@1.0.4", "", { "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" } }, "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw=="], - - "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - - "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], - - "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - - "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="], - - "snapdragon": ["snapdragon@0.8.2", "", { "dependencies": { "base": "^0.11.1", "debug": "^2.2.0", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "map-cache": "^0.2.2", "source-map": "^0.5.6", "source-map-resolve": "^0.5.0", "use": "^3.1.0" } }, "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg=="], - - "snapdragon-node": ["snapdragon-node@2.1.1", "", { "dependencies": { "define-property": "^1.0.0", "isobject": "^3.0.0", "snapdragon-util": "^3.0.1" } }, "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw=="], - - "snapdragon-util": ["snapdragon-util@3.0.1", "", { "dependencies": { "kind-of": "^3.2.0" } }, "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ=="], - - "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], - - "source-map-js": ["source-map-js@1.0.2", "", {}, "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="], - - "source-map-resolve": ["source-map-resolve@0.5.3", "", { "dependencies": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", "urix": "^0.1.0" } }, "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw=="], - - "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], - - "source-map-url": ["source-map-url@0.4.1", "", {}, "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="], - - "split-string": ["split-string@3.1.0", "", { "dependencies": { "extend-shallow": "^3.0.0" } }, "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw=="], - - "split2": ["split2@3.2.2", "", { "dependencies": { "readable-stream": "^3.0.0" } }, "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg=="], - - "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], - - "srcset": ["srcset@3.0.1", "", {}, "sha512-MM8wDGg5BQJEj94tDrZDrX9wrC439/Eoeg3sgmVLPMjHgrAFeXAKk3tmFlCbKw5k+yOEhPXRpPlRcisQmqWVSQ=="], - - "sshpk": ["sshpk@1.17.0", "", { "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", "sshpk-sign": "bin/sshpk-sign", "sshpk-verify": "bin/sshpk-verify" } }, "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ=="], - - "stable": ["stable@0.1.8", "", {}, "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w=="], - - "stacktrace-parser": ["stacktrace-parser@0.1.10", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg=="], - - "static-extend": ["static-extend@0.1.2", "", { "dependencies": { "define-property": "^0.2.5", "object-copy": "^0.1.0" } }, "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g=="], - - "statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], - - "stealthy-require": ["stealthy-require@1.1.1", "", {}, "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g=="], - - "stream-browserify": ["stream-browserify@3.0.0", "", { "dependencies": { "inherits": "~2.0.4", "readable-stream": "^3.5.0" } }, "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA=="], - - "stream-http": ["stream-http@3.1.1", "", { "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.4", "readable-stream": "^3.6.0", "xtend": "^4.0.2" } }, "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg=="], - - "stream-parser": ["stream-parser@0.3.1", "", { "dependencies": { "debug": "2" } }, "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ=="], - - "string-convert": ["string-convert@0.2.1", "", {}, "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="], - - "string-hash": ["string-hash@1.1.3", "", {}, "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A=="], - - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string.prototype.trimend": ["string.prototype.trimend@1.0.6", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.20.4" } }, "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ=="], - - "string.prototype.trimstart": ["string.prototype.trimstart@1.0.6", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.20.4" } }, "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA=="], - - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - - "strip-ansi": ["strip-ansi@6.0.0", "", { "dependencies": { "ansi-regex": "^5.0.0" } }, "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w=="], - - "styled-jsx": ["styled-jsx@4.0.1", "", { "dependencies": { "@babel/plugin-syntax-jsx": "7.14.5", "@babel/types": "7.15.0", "convert-source-map": "1.7.0", "loader-utils": "1.2.3", "source-map": "0.7.3", "string-hash": "1.1.3", "stylis": "3.5.4", "stylis-rule-sheet": "0.0.10" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || 18.x.x" } }, "sha512-Gcb49/dRB1k8B4hdK8vhW27Rlb2zujCk1fISrizCcToIs+55B4vmUM0N9Gi4nnVfFZWe55jRdWpAqH1ldAKWvQ=="], - - "stylehacks": ["stylehacks@4.0.3", "", { "dependencies": { "browserslist": "^4.0.0", "postcss": "^7.0.0", "postcss-selector-parser": "^3.0.0" } }, "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g=="], - - "stylis": ["stylis@4.1.3", "", {}, "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="], - - "stylis-rule-sheet": ["stylis-rule-sheet@0.0.10", "", { "peerDependencies": { "stylis": "^3.5.0" } }, "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="], - - "supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], - - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - - "svgo": ["svgo@1.3.2", "", { "dependencies": { "chalk": "^2.4.1", "coa": "^2.0.2", "css-select": "^2.0.0", "css-select-base-adapter": "^0.1.1", "css-tree": "1.0.0-alpha.37", "csso": "^4.0.2", "js-yaml": "^3.13.1", "mkdirp": "~0.5.1", "object.values": "^1.1.0", "sax": "~1.2.4", "stable": "^0.1.8", "unquote": "~1.1.1", "util.promisify": "~1.0.0" }, "bin": { "svgo": "./bin/svgo" } }, "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw=="], - - "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="], - - "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="], - - "terser": ["terser@5.16.4", "", { "dependencies": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-5yEGuZ3DZradbogeYQ1NaGz7rXVBDWujWlx1PT8efXO6Txn+eWbfKqB2bTDVmFXmePFkoLU6XI8UektMIEA0ug=="], - - "timers-browserify": ["timers-browserify@2.0.12", "", { "dependencies": { "setimmediate": "^1.0.4" } }, "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ=="], - - "timsort": ["timsort@0.3.0", "", {}, "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A=="], - - "to-arraybuffer": ["to-arraybuffer@1.0.1", "", {}, "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA=="], - - "to-fast-properties": ["to-fast-properties@2.0.0", "", {}, "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="], - - "to-object-path": ["to-object-path@0.3.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg=="], - - "to-regex": ["to-regex@3.0.2", "", { "dependencies": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" } }, "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw=="], - - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - - "toggle-selection": ["toggle-selection@1.0.6", "", {}, "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="], - - "toidentifier": ["toidentifier@1.0.0", "", {}, "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="], - - "tough-cookie": ["tough-cookie@2.5.0", "", { "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" } }, "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g=="], - - "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - - "ts-pnp": ["ts-pnp@1.2.0", "", {}, "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw=="], - - "tty-browserify": ["tty-browserify@0.0.1", "", {}, "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw=="], - - "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], - - "tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="], - - "type-check": ["type-check@0.3.2", "", { "dependencies": { "prelude-ls": "~1.1.2" } }, "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg=="], - - "type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="], - - "typed-array-length": ["typed-array-length@1.0.4", "", { "dependencies": { "call-bind": "^1.0.2", "for-each": "^0.3.3", "is-typed-array": "^1.1.9" } }, "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng=="], - - "typescript": ["typescript@4.9.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="], - - "unbox-primitive": ["unbox-primitive@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw=="], - - "uncontrollable": ["uncontrollable@7.2.1", "", { "dependencies": { "@babel/runtime": "^7.6.3", "@types/react": ">=16.9.11", "invariant": "^2.2.4", "react-lifecycles-compat": "^3.0.4" }, "peerDependencies": { "react": ">=15.0.0" } }, "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ=="], - - "uncss": ["uncss@0.17.3", "", { "dependencies": { "commander": "^2.20.0", "glob": "^7.1.4", "is-absolute-url": "^3.0.1", "is-html": "^1.1.0", "jsdom": "^14.1.0", "lodash": "^4.17.15", "postcss": "^7.0.17", "postcss-selector-parser": "6.0.2", "request": "^2.88.0" }, "bin": { "uncss": "bin/uncss" } }, "sha512-ksdDWl81YWvF/X14fOSw4iu8tESDHFIeyKIeDrK6GEVTQvqJc1WlOEXqostNwOCi3qAj++4EaLsdAgPmUbEyog=="], - - "union-value": ["union-value@1.0.1", "", { "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" } }, "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg=="], - - "uniq": ["uniq@1.0.1", "", {}, "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA=="], - - "uniqs": ["uniqs@2.0.0", "", {}, "sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ=="], - - "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - - "unquote": ["unquote@1.1.1", "", {}, "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg=="], - - "unset-value": ["unset-value@1.0.0", "", { "dependencies": { "has-value": "^0.3.1", "isobject": "^3.0.0" } }, "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ=="], - - "update-browserslist-db": ["update-browserslist-db@1.0.10", "", { "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "browserslist-lint": "cli.js" } }, "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - - "urix": ["urix@0.1.0", "", {}, "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg=="], - - "url": ["url@0.11.0", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ=="], - - "use": ["use@3.1.1", "", {}, "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="], - - "use-subscription": ["use-subscription@1.5.1", "", { "dependencies": { "object-assign": "^4.1.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0" } }, "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA=="], - - "util": ["util@0.12.4", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "safe-buffer": "^5.1.2", "which-typed-array": "^1.1.2" } }, "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw=="], - - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - - "util.promisify": ["util.promisify@1.0.1", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.2", "has-symbols": "^1.0.1", "object.getownpropertydescriptors": "^2.1.0" } }, "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA=="], - - "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - - "uuid": ["uuid@3.4.0", "", { "bin": { "uuid": "./bin/uuid" } }, "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="], - - "v8-compile-cache": ["v8-compile-cache@2.3.0", "", {}, "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA=="], - - "vendors": ["vendors@1.0.4", "", {}, "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w=="], - - "verror": ["verror@1.10.0", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw=="], - - "vm-browserify": ["vm-browserify@1.1.2", "", {}, "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="], - - "w3c-hr-time": ["w3c-hr-time@1.0.2", "", { "dependencies": { "browser-process-hrtime": "^1.0.0" } }, "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ=="], - - "w3c-xmlserializer": ["w3c-xmlserializer@1.1.2", "", { "dependencies": { "domexception": "^1.0.1", "webidl-conversions": "^4.0.2", "xml-name-validator": "^3.0.0" } }, "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg=="], - - "warning": ["warning@4.0.3", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w=="], - - "watchpack": ["watchpack@2.1.1", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw=="], - - "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], - - "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - - "whatwg-encoding": ["whatwg-encoding@1.0.5", "", { "dependencies": { "iconv-lite": "0.4.24" } }, "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw=="], - - "whatwg-mimetype": ["whatwg-mimetype@2.3.0", "", {}, "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="], - - "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], - - "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], - - "which-boxed-primitive": ["which-boxed-primitive@1.0.2", "", { "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" } }, "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg=="], - - "which-typed-array": ["which-typed-array@1.1.9", "", { "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0", "is-typed-array": "^1.1.10" } }, "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA=="], - - "word-wrap": ["word-wrap@1.2.3", "", {}, "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="], - - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - - "ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="], - - "xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="], - - "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="], - - "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], - - "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], - - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - - "@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.2", "", { "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A=="], - - "@babel/helper-compilation-targets/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - - "@jridgewell/source-map/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.2", "", { "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } }, "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A=="], - - "@next/react-dev-overlay/@babel/code-frame": ["@babel/code-frame@7.12.11", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw=="], - - "@next/react-dev-overlay/chalk": ["chalk@4.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A=="], - - "@next/react-dev-overlay/classnames": ["classnames@2.2.6", "", {}, "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="], - - "@next/react-dev-overlay/source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="], - - "@next/react-refresh-utils/react-refresh": ["react-refresh@0.8.3", "", {}, "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="], - - "@parcel/codeframe/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "@parcel/core/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "@parcel/core/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], - - "@parcel/core/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/markdown-ansi/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "@parcel/node-libs-browser/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], - - "@parcel/node-libs-browser/domain-browser": ["domain-browser@3.5.0", "", {}, "sha512-zrzUu6auyZWRexjCEPJnfWc30Hupxh2lJZOJAF3qa2bCuD4O/55t0FvQt3ZMhEw++gjNkwdkOVZh8yA32w/Vfw=="], - - "@parcel/node-libs-browser/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "@parcel/node-libs-browser/stream-http": ["stream-http@3.2.0", "", { "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.4", "readable-stream": "^3.6.0", "xtend": "^4.0.2" } }, "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A=="], - - "@parcel/node-libs-browser/util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], - - "@parcel/node-resolver-core/micromatch": ["micromatch@3.1.10", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="], - - "@parcel/optimizer-cssnano/postcss": ["postcss@8.4.21", "", { "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg=="], - - "@parcel/package-manager/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/packager-css/postcss": ["postcss@8.4.21", "", { "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg=="], - - "@parcel/packager-js/globals": ["globals@13.20.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ=="], - - "@parcel/reporter-cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "@parcel/reporter-cli/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@parcel/transformer-babel/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "@parcel/transformer-babel/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/transformer-css/postcss": ["postcss@8.4.21", "", { "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg=="], - - "@parcel/transformer-css/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/transformer-html/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/transformer-js/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "@parcel/transformer-js/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/transformer-postcss/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/transformer-posthtml/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "@parcel/utils/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "@parcel/utils/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], - - "@vitejs/plugin-react-refresh/react-refresh": ["react-refresh@0.10.0", "", {}, "sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ=="], - - "acorn-globals/acorn": ["acorn@6.4.2", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ=="], - - "asn1.js/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], - - "assert/util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], - - "base/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA=="], - - "bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], - - "bl/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "browserify-sign/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "caller-callsite/callsites": ["callsites@2.0.0", "", {}, "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="], - - "caniuse-api/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "class-utils/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="], - - "color-string/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "create-ecdh/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], - - "cross-spawn/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], - - "css-declaration-sorter/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "css-modules-loader-core/postcss": ["postcss@6.0.1", "", { "dependencies": { "chalk": "^1.1.3", "source-map": "^0.5.6", "supports-color": "^3.2.3" } }, "sha512-VbGX1LQgQbf9l3cZ3qbUuC3hGqIEOGQFHAEHQ/Diaeo0yLgpgK5Rb8J+OcamIfQ9PbAU/fzBjVtQX3AhJHUvZw=="], - - "css-select/domutils": ["domutils@1.7.0", "", { "dependencies": { "dom-serializer": "0", "domelementtype": "1" } }, "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg=="], - - "css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "cssnano/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="], - - "cssnano/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "cssnano-preset-default/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "cssnano-util-raw-cache/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "csso/css-tree": ["css-tree@1.1.3", "", { "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" } }, "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="], - - "data-urls/whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], - - "defaults/clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], - - "diffie-hellman/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], - - "dom-serializer/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], - - "domexception/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], - - "domutils/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], - - "elliptic/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], - - "emphasize/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="], - - "expand-brackets/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], - - "extglob/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA=="], - - "extglob/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], - - "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "generic-names/loader-utils": ["loader-utils@1.4.2", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^1.0.1" } }, "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg=="], - - "globby/fast-glob": ["fast-glob@3.2.12", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w=="], - - "has-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], - - "has-values/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg=="], - - "has-values/kind-of": ["kind-of@4.0.0", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw=="], - - "hash-base/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "icss-utils/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "jsdom/acorn": ["acorn@6.4.2", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ=="], - - "jsdom/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], - - "jsdom/whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], - - "jsdom/ws": ["ws@6.2.2", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw=="], - - "loader-utils/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], - - "log-symbols/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "miller-rabin/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], - - "next/@babel/runtime": ["@babel/runtime@7.15.3", "", { "dependencies": { "regenerator-runtime": "^0.13.4" } }, "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA=="], - - "next/react-refresh": ["react-refresh@0.8.3", "", {}, "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="], - - "node-libs-browser/assert": ["assert@1.5.0", "", { "dependencies": { "object-assign": "^4.1.1", "util": "0.10.3" } }, "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA=="], - - "node-libs-browser/buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="], - - "node-libs-browser/domain-browser": ["domain-browser@1.2.0", "", {}, "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="], - - "node-libs-browser/path-browserify": ["path-browserify@0.0.1", "", {}, "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ=="], - - "node-libs-browser/stream-browserify": ["stream-browserify@2.0.2", "", { "dependencies": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" } }, "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg=="], - - "node-libs-browser/stream-http": ["stream-http@2.8.3", "", { "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" } }, "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw=="], - - "node-libs-browser/tty-browserify": ["tty-browserify@0.0.0", "", {}, "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw=="], - - "node-libs-browser/util": ["util@0.11.1", "", { "dependencies": { "inherits": "2.0.3" } }, "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ=="], - - "object-copy/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="], - - "object-copy/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "ora/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - - "parcel/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-calc/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-colormin/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "postcss-colormin/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-colormin/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-convert-values/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-convert-values/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-discard-comments/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-discard-duplicates/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-discard-empty/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-discard-overridden/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-merge-longhand/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-merge-longhand/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-merge-rules/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "postcss-merge-rules/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-merge-rules/postcss-selector-parser": ["postcss-selector-parser@3.1.2", "", { "dependencies": { "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } }, "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA=="], - - "postcss-minify-font-values/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-minify-font-values/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-minify-gradients/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-minify-gradients/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-minify-params/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "postcss-minify-params/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-minify-params/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-minify-selectors/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-minify-selectors/postcss-selector-parser": ["postcss-selector-parser@3.1.2", "", { "dependencies": { "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } }, "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA=="], - - "postcss-modules/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-modules/postcss-modules-extract-imports": ["postcss-modules-extract-imports@2.0.0", "", { "dependencies": { "postcss": "^7.0.5" } }, "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ=="], - - "postcss-modules/postcss-modules-local-by-default": ["postcss-modules-local-by-default@3.0.3", "", { "dependencies": { "icss-utils": "^4.1.1", "postcss": "^7.0.32", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.1.0" } }, "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw=="], - - "postcss-modules/postcss-modules-scope": ["postcss-modules-scope@2.2.0", "", { "dependencies": { "postcss": "^7.0.6", "postcss-selector-parser": "^6.0.0" } }, "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ=="], - - "postcss-modules/postcss-modules-values": ["postcss-modules-values@3.0.0", "", { "dependencies": { "icss-utils": "^4.0.0", "postcss": "^7.0.6" } }, "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg=="], - - "postcss-modules-extract-imports/postcss": ["postcss@6.0.23", "", { "dependencies": { "chalk": "^2.4.1", "source-map": "^0.6.1", "supports-color": "^5.4.0" } }, "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag=="], - - "postcss-modules-local-by-default/postcss": ["postcss@6.0.23", "", { "dependencies": { "chalk": "^2.4.1", "source-map": "^0.6.1", "supports-color": "^5.4.0" } }, "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag=="], - - "postcss-modules-scope/postcss": ["postcss@6.0.23", "", { "dependencies": { "chalk": "^2.4.1", "source-map": "^0.6.1", "supports-color": "^5.4.0" } }, "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag=="], - - "postcss-modules-values/postcss": ["postcss@6.0.23", "", { "dependencies": { "chalk": "^2.4.1", "source-map": "^0.6.1", "supports-color": "^5.4.0" } }, "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag=="], - - "postcss-normalize-charset/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-display-values/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-display-values/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-positions/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-positions/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-repeat-style/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-repeat-style/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-string/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-string/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-timing-functions/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-timing-functions/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-unicode/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "postcss-normalize-unicode/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-unicode/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-url/is-absolute-url": ["is-absolute-url@2.1.0", "", {}, "sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg=="], - - "postcss-normalize-url/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-url/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-normalize-whitespace/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-normalize-whitespace/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-ordered-values/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-ordered-values/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-reduce-initial/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "postcss-reduce-initial/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-reduce-transforms/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-reduce-transforms/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-svgo/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "postcss-svgo/postcss-value-parser": ["postcss-value-parser@3.3.1", "", {}, "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="], - - "postcss-unique-selectors/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "posthtml/posthtml-parser": ["posthtml-parser@0.7.2", "", { "dependencies": { "htmlparser2": "^6.0.0" } }, "sha512-LjEEG/3fNcWZtBfsOE3Gbyg1Li4CmsZRkH1UmbMR7nKdMXVMYI3B4/ZMiCpaq8aI1Aym4FRMMW9SAOLSwOnNsQ=="], - - "posthtml/posthtml-render": ["posthtml-render@1.3.1", "", {}, "sha512-eSToKjNLu0FiF76SSGMHjOFXYzAc/CJqi677Sq6hYvcvFCBtD6de/W5l+0IYPf7ypscqAfjCttxvTdMJt5Gj8Q=="], - - "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - - "prop-types-extra/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - - "public-encrypt/bn.js": ["bn.js@4.12.0", "", {}, "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="], - - "purgecss/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], - - "purgecss/postcss": ["postcss@7.0.32", "", { "dependencies": { "chalk": "^2.4.2", "source-map": "^0.6.1", "supports-color": "^6.1.0" } }, "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw=="], - - "raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "rc-image/@rc-component/portal": ["@rc-component/portal@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "rc-util": "^5.24.4" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-tbXM9SB1r5FOuZjRCljERFByFiEUcMmCWMXLog/NmgCzlAzreXyf23Vei3ZpSMxSMavzPnhCovfZjZdmxS3d1w=="], - - "rc-util/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - - "readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - - "request/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "serve-handler/bytes": ["bytes@3.0.0", "", {}, "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw=="], - - "set-value/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], - - "set-value/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "simple-swizzle/is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], - - "slice-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "snapdragon/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "snapdragon/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="], - - "snapdragon/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], - - "snapdragon-node/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA=="], - - "snapdragon-util/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "split2/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "static-extend/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="], - - "stream-browserify/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "stream-http/readable-stream": ["readable-stream@3.6.0", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="], - - "stream-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - - "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "styled-jsx/@babel/types": ["@babel/types@7.15.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" } }, "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ=="], - - "styled-jsx/convert-source-map": ["convert-source-map@1.7.0", "", { "dependencies": { "safe-buffer": "~5.1.1" } }, "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA=="], - - "styled-jsx/source-map": ["source-map@0.7.3", "", {}, "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="], - - "styled-jsx/stylis": ["stylis@3.5.4", "", {}, "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="], - - "stylehacks/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "stylehacks/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "stylehacks/postcss-selector-parser": ["postcss-selector-parser@3.1.2", "", { "dependencies": { "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } }, "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA=="], - - "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - - "to-object-path/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "tough-cookie/punycode": ["punycode@2.3.0", "", {}, "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="], - - "uncss/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - - "uncss/postcss": ["postcss@7.0.39", "", { "dependencies": { "picocolors": "^0.2.1", "source-map": "^0.6.1" } }, "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA=="], - - "uncss/postcss-selector-parser": ["postcss-selector-parser@6.0.2", "", { "dependencies": { "cssesc": "^3.0.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } }, "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg=="], - - "union-value/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "unset-value/has-value": ["has-value@0.3.1", "", { "dependencies": { "get-value": "^2.0.3", "has-values": "^0.1.4", "isobject": "^2.0.0" } }, "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q=="], - - "update-browserslist-db/browserslist": ["browserslist@4.21.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" } }, "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w=="], - - "uri-js/punycode": ["punycode@2.3.0", "", {}, "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="], - - "url/punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], - - "url/querystring": ["querystring@0.2.0", "", {}, "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="], - - "verror/core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="], - - "verror/extsprintf": ["extsprintf@1.4.1", "", {}, "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA=="], - - "w3c-xmlserializer/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], - - "whatwg-encoding/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - - "@babel/helper-compilation-targets/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - - "@next/react-dev-overlay/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@next/react-dev-overlay/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "@next/react-dev-overlay/source-map/whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], - - "@parcel/codeframe/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@parcel/codeframe/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "@parcel/core/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "@parcel/markdown-ansi/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@parcel/markdown-ansi/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "@parcel/node-resolver-core/micromatch/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], - - "@parcel/packager-js/globals/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], - - "@parcel/reporter-cli/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@parcel/reporter-cli/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "@parcel/transformer-babel/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "@parcel/transformer-js/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "@parcel/utils/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "@parcel/utils/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "caniuse-api/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "class-utils/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], - - "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "css-declaration-sorter/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "css-declaration-sorter/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "css-modules-loader-core/postcss/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="], - - "css-modules-loader-core/postcss/supports-color": ["supports-color@3.2.3", "", { "dependencies": { "has-flag": "^1.0.0" } }, "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A=="], - - "css-select/domutils/dom-serializer": ["dom-serializer@0.2.2", "", { "dependencies": { "domelementtype": "^2.0.1", "entities": "^2.0.0" } }, "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g=="], - - "css-select/domutils/domelementtype": ["domelementtype@1.3.1", "", {}, "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="], - - "cssnano-preset-default/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "cssnano-preset-default/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "cssnano-util-raw-cache/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "cssnano-util-raw-cache/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "cssnano/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="], - - "cssnano/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="], - - "cssnano/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "cssnano/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "csso/css-tree/mdn-data": ["mdn-data@2.0.14", "", {}, "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="], - - "csso/css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "data-urls/whatwg-url/tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], - - "data-urls/whatwg-url/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], - - "emphasize/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "emphasize/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "expand-brackets/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], - - "expand-brackets/extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "extglob/extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "generic-names/loader-utils/emojis-list": ["emojis-list@3.0.0", "", {}, "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="], - - "generic-names/loader-utils/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], - - "has-values/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "icss-utils/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "icss-utils/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "jest-worker/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "jsdom/whatwg-url/tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], - - "log-symbols/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "log-symbols/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "node-libs-browser/assert/util": ["util@0.10.3", "", { "dependencies": { "inherits": "2.0.1" } }, "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ=="], - - "node-libs-browser/util/inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="], - - "object-copy/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], - - "ora/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "ora/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "parcel/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "parcel/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "postcss-calc/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-calc/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-colormin/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "postcss-colormin/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-colormin/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-convert-values/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-convert-values/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-discard-comments/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-discard-comments/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-discard-duplicates/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-discard-duplicates/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-discard-empty/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-discard-empty/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-discard-overridden/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-discard-overridden/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-merge-longhand/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-merge-longhand/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-merge-rules/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "postcss-merge-rules/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-merge-rules/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-minify-font-values/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-minify-font-values/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-minify-gradients/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-minify-gradients/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-minify-params/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "postcss-minify-params/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-minify-params/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-minify-selectors/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-minify-selectors/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-modules-extract-imports/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-modules-local-by-default/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-modules-scope/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-modules-values/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-modules/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-modules/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-charset/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-charset/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-display-values/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-display-values/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-positions/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-positions/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-repeat-style/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-repeat-style/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-string/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-string/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-timing-functions/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-timing-functions/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-unicode/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "postcss-normalize-unicode/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-unicode/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-url/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-url/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-normalize-whitespace/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-normalize-whitespace/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-ordered-values/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-ordered-values/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-reduce-initial/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "postcss-reduce-initial/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-reduce-initial/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-reduce-transforms/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-reduce-transforms/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-svgo/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-svgo/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "postcss-unique-selectors/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "postcss-unique-selectors/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "posthtml/posthtml-parser/htmlparser2": ["htmlparser2@6.1.0", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.0.0", "domutils": "^2.5.2", "entities": "^2.0.0" } }, "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A=="], - - "purgecss/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "purgecss/postcss/supports-color": ["supports-color@6.1.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ=="], - - "request/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "slice-ansi/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "snapdragon/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "snapdragon/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], - - "snapdragon/extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "static-extend/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], - - "stream-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - - "styled-jsx/convert-source-map/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "stylehacks/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "stylehacks/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "stylehacks/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "uncss/postcss/picocolors": ["picocolors@0.2.1", "", {}, "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="], - - "uncss/postcss/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "unset-value/has-value/has-values": ["has-values@0.1.4", "", {}, "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="], - - "unset-value/has-value/isobject": ["isobject@2.1.0", "", { "dependencies": { "isarray": "1.0.0" } }, "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA=="], - - "update-browserslist-db/browserslist/node-releases": ["node-releases@2.0.10", "", {}, "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="], - - "@next/react-dev-overlay/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "@next/react-dev-overlay/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "@next/react-dev-overlay/source-map/whatwg-url/tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], - - "@next/react-dev-overlay/source-map/whatwg-url/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], - - "@parcel/codeframe/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "@parcel/codeframe/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "@parcel/markdown-ansi/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "@parcel/markdown-ansi/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "@parcel/node-resolver-core/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], - - "@parcel/node-resolver-core/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ=="], - - "@parcel/reporter-cli/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "@parcel/reporter-cli/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "@parcel/utils/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "@parcel/utils/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "class-utils/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A=="], - - "class-utils/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg=="], - - "class-utils/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], - - "css-modules-loader-core/postcss/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="], - - "css-modules-loader-core/postcss/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "css-modules-loader-core/postcss/chalk/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="], - - "css-modules-loader-core/postcss/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="], - - "css-modules-loader-core/postcss/supports-color/has-flag": ["has-flag@1.0.0", "", {}, "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA=="], - - "css-select/domutils/dom-serializer/domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], - - "cssnano/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="], - - "data-urls/whatwg-url/tr46/punycode": ["punycode@2.3.0", "", {}, "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="], - - "emphasize/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "emphasize/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "expand-brackets/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A=="], - - "expand-brackets/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg=="], - - "expand-brackets/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], - - "jsdom/whatwg-url/tr46/punycode": ["punycode@2.3.0", "", {}, "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="], - - "log-symbols/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "log-symbols/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "node-libs-browser/assert/util/inherits": ["inherits@2.0.1", "", {}, "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA=="], - - "object-copy/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A=="], - - "object-copy/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg=="], - - "object-copy/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], - - "ora/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "ora/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "parcel/chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "parcel/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "posthtml/posthtml-parser/htmlparser2/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="], - - "slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "snapdragon/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A=="], - - "snapdragon/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg=="], - - "snapdragon/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], - - "static-extend/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A=="], - - "static-extend/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg=="], - - "static-extend/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], - - "@next/react-dev-overlay/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "@next/react-dev-overlay/source-map/whatwg-url/tr46/punycode": ["punycode@2.3.0", "", {}, "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="], - - "@parcel/codeframe/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "@parcel/markdown-ansi/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "@parcel/node-resolver-core/micromatch/braces/extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], - - "@parcel/node-resolver-core/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg=="], - - "@parcel/node-resolver-core/micromatch/braces/fill-range/to-regex-range": ["to-regex-range@2.1.1", "", { "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" } }, "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg=="], - - "@parcel/reporter-cli/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "@parcel/utils/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "class-utils/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "class-utils/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "css-modules-loader-core/postcss/chalk/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], - - "emphasize/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "expand-brackets/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "expand-brackets/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "object-copy/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "object-copy/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "parcel/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "snapdragon/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "snapdragon/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "static-extend/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "static-extend/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - - "@parcel/node-resolver-core/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], - } -} diff --git a/examples/react-fast-refresh-test/package.json b/examples/react-fast-refresh-test/package.json deleted file mode 100644 index 24b2082ee3..0000000000 --- a/examples/react-fast-refresh-test/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "simple-react", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@emotion/css": "^11.1.3", - "@vitejs/plugin-react-refresh": "^1.3.3", - "antd": "^4.16.1", - "left-pad": "^1.3.0", - "next": "^11.0.0", - "parcel": "2.0.0-beta.3", - "react": "^17.0.2", - "react-bootstrap": "^1.6.1", - "react-dom": "^17.0.2", - "react-form": "^4.0.1", - "react-hook-form": "^7.8.3" - }, - "parcel": "parceldist/index.js", - "targets": { - "parcel": { - "outputFormat": "esmodule", - "sourceMap": false, - "optimize": false, - "engines": { - "chrome": "last 1 version" - } - } - }, - "devDependencies": { - "@snowpack/plugin-react-refresh": "^2.5.0", - "typescript": "^4.3.4" - } -} diff --git a/examples/react-fast-refresh-test/public/index.html b/examples/react-fast-refresh-test/public/index.html deleted file mode 100644 index 2032ea287b..0000000000 --- a/examples/react-fast-refresh-test/public/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - -
- - - - diff --git a/examples/react-fast-refresh-test/src/button.css b/examples/react-fast-refresh-test/src/button.css deleted file mode 100644 index 60db46096a..0000000000 --- a/examples/react-fast-refresh-test/src/button.css +++ /dev/null @@ -1,11758 +0,0 @@ -body { - background-color: red; - border: 10px solid red; - color: pink; - box-shadow: 10px 10px 32px red; -} - -body { - background-color: blue; -} - -body { - background-color: aliceblue; -} - -body { - background-color: red; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: red; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: yellow; -} - -body { - background-color: red; -} diff --git a/examples/react-fast-refresh-test/src/colors.css b/examples/react-fast-refresh-test/src/colors.css deleted file mode 100644 index 06a1853436..0000000000 --- a/examples/react-fast-refresh-test/src/colors.css +++ /dev/null @@ -1,14 +0,0 @@ -:root { - --timestamp: "0"; - --interval: "8"; - --progress-bar: 11.83299999999997%; - --spinner-1-muted: rgb(142, 6, 182); - --spinner-1-primary: rgb(177, 8, 227); - --spinner-2-muted: rgb(110, 148, 190); - --spinner-2-primary: rgb(138, 185, 238); - --spinner-3-muted: rgb(75, 45, 64); - --spinner-3-primary: rgb(94, 56, 80); - --spinner-4-muted: rgb(155, 129, 108); - --spinner-4-primary: rgb(194, 161, 135); - --spinner-rotate: 213deg; -} diff --git a/examples/react-fast-refresh-test/src/components/RenderCounter.tsx b/examples/react-fast-refresh-test/src/components/RenderCounter.tsx deleted file mode 100644 index ed2f00b568..0000000000 --- a/examples/react-fast-refresh-test/src/components/RenderCounter.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; - -export function RenderCounter({ name, children }) { - const counter = React.useRef(1); - return ( -
-
-
- {name} rendered {counter.current++} times -
-
- LAST RENDER:{" "} - {new Intl.DateTimeFormat([], { - timeStyle: "long", - }).format(new Date())} -
-
-
{children}
-
- ); -} diff --git a/examples/react-fast-refresh-test/src/components/app.tsx b/examples/react-fast-refresh-test/src/components/app.tsx deleted file mode 100644 index 2edc025457..0000000000 --- a/examples/react-fast-refresh-test/src/components/app.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from "react"; -import { Button } from "./Button"; -import { RenderCounter } from "./RenderCounter"; -export function App() { - return ( - -
-

This is the root element

- - -
-
- ); -} diff --git a/examples/react-fast-refresh-test/src/components/button.tsx b/examples/react-fast-refresh-test/src/components/button.tsx deleted file mode 100644 index 4c33886700..0000000000 --- a/examples/react-fast-refresh-test/src/components/button.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { RenderCounter } from "./RenderCounter"; - -export const Button = ({ children }) => { - return ( - -
{children}
-
- ); -}; diff --git a/examples/react-fast-refresh-test/src/font.css b/examples/react-fast-refresh-test/src/font.css deleted file mode 100644 index 448775ef02..0000000000 --- a/examples/react-fast-refresh-test/src/font.css +++ /dev/null @@ -1 +0,0 @@ -@import "https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;700&family=Space+Mono:wght@400;700&display=swap"; diff --git a/examples/react-fast-refresh-test/src/index.css b/examples/react-fast-refresh-test/src/index.css deleted file mode 100644 index c4514199cd..0000000000 --- a/examples/react-fast-refresh-test/src/index.css +++ /dev/null @@ -1,98 +0,0 @@ -@import "./colors.css"; - -:root { - --heading-font: "Space Mono", system-ui; - --body-font: "IBM Plex Sans", system-ui; - - --color-brand: #02ff00; - --color-brand-muted: rgb(2, 150, 0); - - --padding-horizontal: 90px; - - --page-background: black; - --page-background-alpha: rgba(0, 0, 0, 0.8); - - --result__background-color: black; - --result__primary-color: var(--color-brand); - --result__foreground-color: white; - --result__muted-color: rgb(165, 165, 165); - - --card-width: 352px; - - --page-width: 1152px; - - --snippets_container-background-unfocused: #171717; - --snippets_container-background-focused: #0017e9; - --snippets_container-background: var( - --snippets_container-background-unfocused - ); - --snippets_container-muted-color: rgb(153, 153, 153); -} - -body { - color: white; - margin: 0; - - padding: 0; - font-family: var(--body-font); - background-color: var(--page-background); - color: var(--result__muted-color); - display: flex; - flex-direction: column; - height: 100%; -} - -#reactroot, -#__next, -body, -html { - height: 100%; -} - -.RenderCounter { - border: 10px solid var(--snippets_container-background-focused); - margin: 10px; - padding: 10px; - animation: flash 0.2s linear; - animation-fill-mode: forwards; -} - -.RenderCounter-meta { - display: flex; - flex-direction: row; - justify-content: space-between; - margin: -10px; - padding: 10px; - background-color: #111; -} - -.RenderCounter-lastRender, -.RenderCounter-title { - white-space: nowrap; - color: rgb(153, 153, 153); -} - -@keyframes flash { - from { - border-color: var(--snippets_container-background-focused); - } - - to { - border-color: var(--snippets_container-background-unfocused); - } -} - -.Button { - display: block; - - border: 1px solid rgb(20, 180, 0); - background-color: rgb(2, 150, 0); - color: white; - font-weight: 500; - padding: 10px 12px; - border-radius: 4px; - text-transform: uppercase; - text-align: center; - width: fit-content; - cursor: pointer; -} diff --git a/examples/react-fast-refresh-test/src/index.tsx b/examples/react-fast-refresh-test/src/index.tsx deleted file mode 100644 index 348bd80f27..0000000000 --- a/examples/react-fast-refresh-test/src/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import ReactDOM from "react-dom"; -import React from "react"; -import { App } from "./components/app"; -import classNames from "classnames"; - -function startReact() { - ReactDOM.render(, document.querySelector("#reactroot")); -} - -globalThis.addEventListener("DOMContentLoaded", () => { - startReact(); -}); -startReact(); - -export { App }; diff --git a/examples/react-fast-refresh-test/src/main.tsx b/examples/react-fast-refresh-test/src/main.tsx deleted file mode 100644 index 928d64b724..0000000000 --- a/examples/react-fast-refresh-test/src/main.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from "react"; - -export const Main = ({ productName }) => { - return ( - <> -
-
CSS HMR Stress Test
-

- This page visually tests how quickly a bundler can update CSS over Hot Module Reloading. -

-
-
-
-

- - Ran:  - -

- -
-
-
-
The progress bar should move from left to right smoothly.
-
- -
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
The spinners should rotate & change color smoothly.
-
-
-
-
There are no CSS animations on this page.
- -
-
{productName}
-
- Saving a css file every  - - ms - -
-
-
- - ); -}; diff --git a/examples/react-fast-refresh-test/tsconfig.json b/examples/react-fast-refresh-test/tsconfig.json deleted file mode 100644 index d543b64724..0000000000 --- a/examples/react-fast-refresh-test/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "target": "esnext", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "strict": false, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve" - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx" - ], - "exclude": [ - "node_modules" - ] -} \ No newline at end of file diff --git a/examples/react-file-system-router/bun.lockb b/examples/react-file-system-router/bun.lockb deleted file mode 100755 index 73ffd9aed2..0000000000 Binary files a/examples/react-file-system-router/bun.lockb and /dev/null differ diff --git a/examples/react-file-system-router/index.tsx b/examples/react-file-system-router/index.tsx deleted file mode 100644 index 2abcc6b7e4..0000000000 --- a/examples/react-file-system-router/index.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// A simple way to connect FileSystemRouter to Bun#serve -// run with `bun run index.tsx` - -import { renderToReadableStream } from "react-dom/server"; -import { FileSystemRouter } from "bun"; - -export default { - port: 3000, - async fetch(request: Request) { - const router = new FileSystemRouter({ - dir: process.cwd() + "/pages", - style: "nextjs", - }); - - const route = router.match(request); - - const { default: Root } = await import(route.filePath!); - return new Response(await renderToReadableStream()); - }, -}; diff --git a/examples/react-file-system-router/package.json b/examples/react-file-system-router/package.json deleted file mode 100644 index 65b80060af..0000000000 --- a/examples/react-file-system-router/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "react-routes", - "module": "index.tsx", - "type": "module", - "devDependencies": { - "@types/react": "^18.0.27", - "@types/react-dom": "^18.0.10", - "bun-types": "^0.7.0" - }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - } -} diff --git a/examples/react-file-system-router/pages/index.tsx b/examples/react-file-system-router/pages/index.tsx deleted file mode 100644 index f1fe2a2e17..0000000000 --- a/examples/react-file-system-router/pages/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// reachable from http://localhost:3000/ - -export default () => ( - - - index - - -

- one -

-

- two -

- - -); diff --git a/examples/react-file-system-router/pages/one.tsx b/examples/react-file-system-router/pages/one.tsx deleted file mode 100644 index b65a32f6c9..0000000000 --- a/examples/react-file-system-router/pages/one.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// reachable from http://localhost:3000/one - -export default () => ( - - - one - - -

one

- - -); diff --git a/examples/react-file-system-router/pages/two.tsx b/examples/react-file-system-router/pages/two.tsx deleted file mode 100644 index c3d8beef9e..0000000000 --- a/examples/react-file-system-router/pages/two.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// reachable from http://localhost:3000/two - -export default () => ( - - - two - - -

two

- - -); diff --git a/examples/react-file-system-router/tsconfig.json b/examples/react-file-system-router/tsconfig.json deleted file mode 100644 index c458f8fe80..0000000000 --- a/examples/react-file-system-router/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "lib": [ - "ESNext" - ], - "module": "esnext", - "target": "esnext", - "moduleResolution": "nodenext", - "strict": false, - "downlevelIteration": true, - "skipLibCheck": true, - "jsx": "preserve", - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "allowJs": true, - "types": [ - "bun-types" // add Bun global - ] - } -} \ No newline at end of file diff --git a/examples/sha.js b/examples/sha.js deleted file mode 100644 index bb7382a038..0000000000 --- a/examples/sha.js +++ /dev/null @@ -1,68 +0,0 @@ -import { SHA1, SHA256, SHA512, SHA384, SHA512_256, MD5, MD4, RIPEMD160, sha } from "bun"; - -const input = "Hello World"; -const [first, second] = input.split(" "); - -const log = (name, ...args) => console.log(`${name}:`.padStart("SHA512_256: ".length), ...args); - -console.log(""); -// This is SHA512-256: -// This function is shorthand for SHA512_256.hash(input) -log("Bun.sha()", sha(input, "base64")); - -log("SHA1", SHA1.hash(input, "hex")); -log("SHA256", SHA256.hash(input, "hex")); -log("SHA384", SHA384.hash(input, "hex")); -log("SHA512", SHA512.hash(input, "hex")); -log("SHA512_256", SHA512_256.hash(input, "hex")); -log("RIPEMD160", RIPEMD160.hash(input, "hex")); - -console.log(""); -console.log("---- Chunked ----"); -console.log(""); - -// You can also do updates in chunks: -// const hash = new Hash(); -for (let Hash of [SHA1, SHA256, SHA384, SHA512, SHA512_256, RIPEMD160]) { - const hash = new Hash(); - hash.update(first); - hash.update(" " + second); - log(Hash.name, hash.digest("hex")); -} - -console.log(""); -console.log("---- Base64 ----"); -console.log(""); - -// base64 or hex -for (let Hash of [SHA1, SHA256, SHA384, SHA512, SHA512_256]) { - const hash = new Hash(); - hash.update(first); - hash.update(" " + second); - log(Hash.name, hash.digest("base64")); -} - -console.log(""); -console.log("---- Uint8Array ----"); -console.log(""); - -// Uint8Array by default -for (let Hash of [SHA1, SHA256, SHA384, SHA512, SHA512_256]) { - const hash = new Hash(); - hash.update(first); - hash.update(" " + second); - log(Hash.name, hash.digest()); -} - -console.log(""); -console.log("---- Uint8Array can be updated in-place ----"); -console.log(""); - -var oneBuf = new Uint8Array(1024); -// Update Uint8Array in-place instead of allocating a new one -for (let Hash of [SHA1, SHA256, SHA384, SHA512, SHA512_256]) { - const hash = new Hash(); - hash.update(first); - hash.update(" " + second); - log(Hash.name, hash.digest(oneBuf).subarray(0, Hash.byteLength)); -} diff --git a/examples/spawn.ts b/examples/spawn.ts deleted file mode 100644 index 520fa60ffb..0000000000 --- a/examples/spawn.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { spawn, which } from "bun"; -import { rmSync } from "fs"; -import { basename } from "path"; - -const repo = process.argv.at(3) || "TheoBr/vercel-vite-demo"; - -const target = basename(repo) + "-main"; -console.log("Downloading", repo, "to", "/tmp/" + target); - -const archive = await fetch(`https://github.com/${repo}/archive/refs/heads/main.tar.gz`); - -// remove the directory if it already exists locally -rmSync("/tmp/" + target, { recursive: true, force: true }); - -const tar = spawn({ - cmd: ["tar", "-xzf", "-"], - stdin: archive.body, - - stderr: "inherit", - stdout: "inherit", - cwd: "/tmp", -}); - -await tar.exited; - -// if vercel isn't installed, install it -if (!which("vercel")) { - console.log("Installing vercel..."); - - const installer = spawn(["bun", "install", "-g", "vercel"], { - stderr: "inherit", - stdout: "inherit", - stdin: "inherit", - }); - await installer.exited; - - if (!which("vercel")) { - throw new Error("Failed to install Vercel CLI"); - } -} - -const { exited: deployed } = spawn({ - cmd: ["vercel", "deploy", "--yes", "--public", target], - stdio: ["inherit", "inherit", "inherit"], - cwd: "/tmp", -}); - -await deployed; diff --git a/examples/ssl.ts b/examples/ssl.ts deleted file mode 100644 index b886649e84..0000000000 --- a/examples/ssl.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { resolve } from "path"; -import type { ServeOptions } from "bun"; - -const development = process.env.NODE_ENV !== "production"; -export default { - fetch(req: Request) { - return new Response(Bun.file(resolve(req.url.substring(1)))); - }, - - // hostname: "0.0.0.0", - port: process.env.PORT || "443", - keyFile: process.env.SSL_KEY_FILE || "./key.pem", - certFile: process.env.SSL_CERTIFICATE_FILE || "./cert.pem", - development, -} as ServeOptions; diff --git a/examples/tcp.ts b/examples/tcp.ts deleted file mode 100644 index b392febd18..0000000000 --- a/examples/tcp.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { listen, connect } from "bun"; - -var counter = 0; -const msg = Buffer.from("Hello World!"); - -const handlers = { - open(socket) { - if (!socket.data?.isServer) { - if (!socket.write(msg)) { - socket.data = { pending: msg }; - } - } - }, - data(socket, buffer) { - if (!socket.write(buffer)) { - socket.data = { pending: buffer }; - return; - } - counter++; - }, - drain(socket) { - const pending = socket.data?.pending; - if (!pending) return; - if (socket.write(pending)) { - socket.data = undefined; - counter++; - return; - } - }, -}; - -setInterval(() => { - console.log("Wrote", counter, "messages"); - counter = 0; -}, 1000); - -const server = listen({ - socket: handlers, - hostname: "localhost", - port: 8080, - data: { - isServer: true, - }, -}); -const connection = await connect({ - socket: handlers, - hostname: "localhost", - port: 8080, -}); diff --git a/misctools/lldb/lldb_pretty_printers.py b/misctools/lldb/lldb_pretty_printers.py index 4b0993ca43..add417d6b1 100644 --- a/misctools/lldb/lldb_pretty_printers.py +++ b/misctools/lldb/lldb_pretty_printers.py @@ -686,7 +686,7 @@ def add(debugger, *, category, regex=False, type, identifier=None, synth=False, if summary: debugger.HandleCommand('type summary add --category %s%s%s "%s"' % (category, ' --inline-children' if inline_children else ''.join((' --expand' if expand else '', ' --python-function %s_SummaryProvider' % prefix if summary == True else ' --summary-string "%s"' % summary)), ' --regex' if regex else '', type)) if synth: debugger.HandleCommand('type synthetic add --category %s%s --python-class %s_SynthProvider "%s"' % (category, ' --regex' if regex else '', prefix, type)) -def MultiArrayList_Entry(type): return '^multi_array_list\\.MultiArrayList\\(%s\\)\\.Entry__struct_[1-9][0-9]*$' % type +def MultiArrayList_Entry(type): return 'multi_array_list\\.MultiArrayList\\(%s\\)\\.Entry__struct_[1-9][0-9]*$' % type def __lldb_init_module(debugger, _=None): # Initialize Zig Categories @@ -701,8 +701,8 @@ def __lldb_init_module(debugger, _=None): # Initialize Zig Standard Library add(debugger, category='zig.std', type='mem.Allocator', summary='${var.ptr}') add(debugger, category='zig.std', regex=True, type='^segmented_list\\.SegmentedList\\(.*\\)$', identifier='std_SegmentedList', synth=True, expand=True, summary='len=${var.len}') - add(debugger, category='zig.std', regex=True, type='^multi_array_list\\.MultiArrayList\\(.*\\)$', identifier='std_MultiArrayList', synth=True, expand=True, summary='len=${var.len} capacity=${var.capacity}') - add(debugger, category='zig.std', regex=True, type='^multi_array_list\\.MultiArrayList\\(.*\\)\\.Slice$', identifier='std_MultiArrayList_Slice', synth=True, expand=True, summary='len=${var.len} capacity=${var.capacity}') + add(debugger, category='zig.std', regex=True, type='multi_array_list\\.MultiArrayList\\(.*\\)$', identifier='std_MultiArrayList', synth=True, expand=True, summary='len=${var.len} capacity=${var.capacity}') + add(debugger, category='zig.std', regex=True, type='multi_array_list\\.MultiArrayList\\(.*\\)\\.Slice$', identifier='std_MultiArrayList_Slice', synth=True, expand=True, summary='len=${var.len} capacity=${var.capacity}') add(debugger, category='zig.std', regex=True, type=MultiArrayList_Entry('.*'), identifier='std_Entry', synth=True, inline_children=True, summary=True) add(debugger, category='zig.std', regex=True, type='^hash_map\\.HashMapUnmanaged\\(.*\\)$', identifier='std_HashMapUnmanaged', synth=True, expand=True, summary=True) add(debugger, category='zig.std', regex=True, type='^hash_map\\.HashMapUnmanaged\\(.*\\)\\.Entry$', identifier = 'std_Entry', synth=True, inline_children=True, summary=True) diff --git a/package.json b/package.json index 40c3547de5..7673ea6ec7 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "source-map-js": "^1.2.0", - "typescript": "^5.7.2" + "typescript": "5.9.2" }, "resolutions": { "bun-types": "workspace:packages/bun-types", diff --git a/packages/bun-plugin-svelte/bun.lock b/packages/bun-plugin-svelte/bun.lock index aa18005aa9..75ce559755 100644 --- a/packages/bun-plugin-svelte/bun.lock +++ b/packages/bun-plugin-svelte/bun.lock @@ -5,7 +5,7 @@ "name": "bun-plugin-svelte", "devDependencies": { "@threlte/core": "8.0.1", - "bun-types": "canary", + "@types/bun": "../bun-types", "svelte": "^5.20.4", }, "peerDependencies": { @@ -28,11 +28,13 @@ "@threlte/core": ["@threlte/core@8.0.1", "", { "dependencies": { "mitt": "^3.0.1" }, "peerDependencies": { "svelte": ">=5", "three": ">=0.155" } }, "sha512-vy1xRQppJFNmfPTeiRQue+KmYFsbPgVhwuYXRTvVrwPeD2oYz43gxUeOpe1FACeGKxrxZykeKJF5ebVvl7gBxw=="], + "@types/bun": ["bun-types@file:../bun-types", { "dependencies": { "@types/node": "*" }, "devDependencies": { "@types/react": "^19" }, "peerDependencies": { "@types/react": "^19" } }], + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], "@types/node": ["@types/node@22.13.5", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg=="], - "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + "@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="], "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], @@ -42,10 +44,10 @@ "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], - "bun-types": ["bun-types@1.2.4-canary.20250226T140704", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-P8b2CGLtbvi/kQ4dPHBhU5qkguIjHMYCjNqjWDTKSnodWDTbcv9reBdktZJ7m5SF4m15JLthfFq2PtwKpA9a+w=="], - "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], "esrap": ["esrap@1.4.5", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-CjNMjkBWWZeHn+VX+gS8YvFwJ5+NDhg8aWZBSFJPR8qQduDNjbJodA2WcwCm7uQa5Rjqj+nZvVmceg1RbHFB9g=="], diff --git a/packages/bun-plugin-svelte/package.json b/packages/bun-plugin-svelte/package.json index b56c2d203e..2fe537baaf 100644 --- a/packages/bun-plugin-svelte/package.json +++ b/packages/bun-plugin-svelte/package.json @@ -23,7 +23,7 @@ "build:types": "tsc --emitDeclarationOnly --declaration --declarationDir ./dist" }, "devDependencies": { - "bun-types": "canary", + "@types/bun": "../bun-types", "svelte": "^5.20.4", "@threlte/core": "8.0.1" }, diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 91f5304d5d..2771f9e9f7 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -21,7 +21,7 @@ declare module "bun" { | DataView; type BufferSource = NodeJS.TypedArray | DataView | ArrayBufferLike; type StringOrBuffer = string | NodeJS.TypedArray | ArrayBufferLike; - type XMLHttpRequestBodyInit = Blob | BufferSource | string | FormData | Iterable; + type XMLHttpRequestBodyInit = Blob | BufferSource | FormData | URLSearchParams | string; type ReadableStreamController = ReadableStreamDefaultController; type ReadableStreamDefaultReadResult = | ReadableStreamDefaultReadValueResult @@ -826,7 +826,7 @@ declare module "bun" { buffers: Array, maxLength: number, asUint8Array: true, - ): Uint8Array; + ): Uint8Array; /** * Consume all data from a {@link ReadableStream} until it closes or errors. @@ -843,35 +843,6 @@ declare module "bun" { stream: ReadableStream, ): Promise | ArrayBuffer; - /** - * Consume all data from a {@link ReadableStream} until it closes or errors. - * - * Concatenate the chunks into a single {@link ArrayBuffer}. - * - * Each chunk must be a TypedArray or an ArrayBuffer. If you need to support - * chunks of different types, consider {@link readableStreamToBlob} - * - * @param stream The stream to consume. - * @returns A promise that resolves with the concatenated chunks or the concatenated chunks as a {@link Uint8Array}. - * - * @deprecated Use {@link ReadableStream.bytes} - */ - function readableStreamToBytes( - stream: ReadableStream, - ): Promise | Uint8Array; - - /** - * Consume all data from a {@link ReadableStream} until it closes or errors. - * - * Concatenate the chunks into a single {@link Blob}. - * - * @param stream The stream to consume. - * @returns A promise that resolves with the concatenated chunks as a {@link Blob}. - * - * @deprecated Use {@link ReadableStream.blob} - */ - function readableStreamToBlob(stream: ReadableStream): Promise; - /** * Consume all data from a {@link ReadableStream} until it closes or errors. * @@ -904,30 +875,6 @@ declare module "bun" { multipartBoundaryExcludingDashes?: string | NodeJS.TypedArray | ArrayBufferView, ): Promise; - /** - * Consume all data from a {@link ReadableStream} until it closes or errors. - * - * Concatenate the chunks into a single string. Chunks must be a TypedArray or an ArrayBuffer. If you need to support chunks of different types, consider {@link readableStreamToBlob}. - * - * @param stream The stream to consume. - * @returns A promise that resolves with the concatenated chunks as a {@link String}. - * - * @deprecated Use {@link ReadableStream.text} - */ - function readableStreamToText(stream: ReadableStream): Promise; - - /** - * Consume all data from a {@link ReadableStream} until it closes or errors. - * - * Concatenate the chunks into a single string and parse as JSON. Chunks must be a TypedArray or an ArrayBuffer. If you need to support chunks of different types, consider {@link readableStreamToBlob}. - * - * @param stream The stream to consume. - * @returns A promise that resolves with the concatenated chunks as a {@link String}. - * - * @deprecated Use {@link ReadableStream.json} - */ - function readableStreamToJSON(stream: ReadableStream): Promise; - /** * Consume all data from a {@link ReadableStream} until it closes or errors. * @@ -1027,8 +974,8 @@ declare module "bun" { * * This API might change later to separate Uint8ArraySink and ArrayBufferSink */ - flush(): number | Uint8Array | ArrayBuffer; - end(): ArrayBuffer | Uint8Array; + flush(): number | Uint8Array | ArrayBuffer; + end(): ArrayBuffer | Uint8Array; } /** DNS Related APIs */ @@ -1595,13 +1542,18 @@ declare module "bun" { * Executes a SQL query using template literals * @example * ```ts - * const [user] = await sql`select * from users where id = ${1}`; + * const [user] = await sql`select * from users where id = ${1}`; * ``` */ (strings: TemplateStringsArray, ...values: unknown[]): SQL.Query; /** * Execute a SQL query using a string + * + * @example + * ```ts + * const users = await sql`SELECT * FROM users WHERE id = ${1}`; + * ``` */ (string: string): SQL.Query; @@ -1620,6 +1572,23 @@ declare module "bun" { * const result = await sql`insert into users ${sql(user)} returning *`; * ``` */ + (obj: T | T[] | readonly T[]): SQL.Helper; + + /** + * Helper function for inserting an object into a query, supporting specific columns + * + * @example + * ```ts + * // Insert an object + * const result = await sql`insert into users ${sql(users)} returning *`; + * + * // Or pick specific columns + * const result = await sql`insert into users ${sql(users, "id", "name")} returning *`; + * + * // Or a single object + * const result = await sql`insert into users ${sql(user)} returning *`; + * ``` + */ ( obj: T | T[] | readonly T[], ...columns: readonly Keys[] @@ -3682,7 +3651,7 @@ declare module "bun" { /** * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) + * (Cannot use unix with port + hostname) */ unix?: never; @@ -3705,9 +3674,21 @@ declare module "bun" { interface UnixServeOptions extends GenericServeOptions { /** * If set, the HTTP server will listen on a unix socket instead of a port. - * (Cannot be used with hostname+port) */ unix: string; + + /** + * If set, the HTTP server will listen on this port + * (Cannot use port with unix) + */ + port?: never; + + /** + * If set, the HTTP server will listen on this hostname + * (Cannot use hostname with unix) + */ + hostname?: never; + /** * Handle HTTP requests * @@ -4635,7 +4616,7 @@ declare module "bun" { * * @param path The path to the file as a byte buffer (the buffer is copied) if the path starts with `s3://` it will behave like {@link S3File} */ - function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; + function file(path: ArrayBufferLike | Uint8Array, options?: BlobPropertyBag): BunFile; /** * [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) powered by the fastest system calls available for operating on files. @@ -4658,7 +4639,7 @@ declare module "bun" { * * This can be 3.5x faster than `new Uint8Array(size)`, but if you send uninitialized memory to your users (even unintentionally), it can potentially leak anything recently in memory. */ - function allocUnsafe(size: number): Uint8Array; + function allocUnsafe(size: number): Uint8Array; /** * Options for `Bun.inspect` @@ -4941,7 +4922,7 @@ declare module "bun" { * * To close the file, set the array to `null` and it will be garbage collected eventually. */ - function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; + function mmap(path: PathLike, opts?: MMapOptions): Uint8Array; /** * Write to stdout @@ -4971,8 +4952,8 @@ declare module "bun" { | { r: number; g: number; b: number; a?: number } | [number, number, number] | [number, number, number, number] - | Uint8Array - | Uint8ClampedArray + | Uint8Array + | Uint8ClampedArray | Float32Array | Float64Array | string @@ -5095,7 +5076,7 @@ declare module "bun" { * * **The input buffer must not be garbage collected**. That means you will need to hold on to it for the duration of the string's lifetime. */ - function arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; + function arrayBufferToString(buffer: Uint8Array | ArrayBufferLike): string; /** * Cast bytes to a `String` without copying. This is the fastest way to get a `String` from a `Uint16Array` @@ -5644,9 +5625,9 @@ declare module "bun" { * @returns The output buffer with the compressed data */ function deflateSync( - data: Uint8Array | string | ArrayBuffer, + data: Uint8Array | string | ArrayBuffer, options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; + ): Uint8Array; /** * Compresses a chunk of data with `zlib` GZIP algorithm. * @param data The buffer of data to compress @@ -5654,27 +5635,27 @@ declare module "bun" { * @returns The output buffer with the compressed data */ function gzipSync( - data: Uint8Array | string | ArrayBuffer, + data: Uint8Array | string | ArrayBuffer, options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; + ): Uint8Array; /** * Decompresses a chunk of data with `zlib` INFLATE algorithm. * @param data The buffer of data to decompress * @returns The output buffer with the decompressed data */ function inflateSync( - data: Uint8Array | string | ArrayBuffer, + data: Uint8Array | string | ArrayBuffer, options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; + ): Uint8Array; /** * Decompresses a chunk of data with `zlib` GUNZIP algorithm. * @param data The buffer of data to decompress * @returns The output buffer with the decompressed data */ function gunzipSync( - data: Uint8Array | string | ArrayBuffer, + data: Uint8Array | string | ArrayBuffer, options?: ZlibCompressionOptions | LibdeflateCompressionOptions, - ): Uint8Array; + ): Uint8Array; /** * Compresses a chunk of data with the Zstandard (zstd) compression algorithm. @@ -6651,7 +6632,7 @@ declare module "bun" { interface BinaryTypeList { arraybuffer: ArrayBuffer; buffer: Buffer; - uint8array: Uint8Array; + uint8array: Uint8Array; // TODO: DataView // dataview: DataView; } @@ -6829,6 +6810,7 @@ declare module "bun" { * The unix socket to listen on or connect to */ unix: string; + /** * TLS Configuration with which to create the socket */ @@ -7223,7 +7205,7 @@ declare module "bun" { } type ReadableToIO = X extends "pipe" | undefined - ? ReadableStream + ? ReadableStream> : X extends BunFile | ArrayBufferView | number ? number : undefined; diff --git a/packages/bun-types/deprecated.d.ts b/packages/bun-types/deprecated.d.ts index c1ce3138e4..0b8cee7818 100644 --- a/packages/bun-types/deprecated.d.ts +++ b/packages/bun-types/deprecated.d.ts @@ -1,4 +1,57 @@ declare module "bun" { + /** + * Consume all data from a {@link ReadableStream} until it closes or errors. + * + * Concatenate the chunks into a single {@link ArrayBuffer}. + * + * Each chunk must be a TypedArray or an ArrayBuffer. If you need to support + * chunks of different types, consider {@link readableStreamToBlob} + * + * @param stream The stream to consume. + * @returns A promise that resolves with the concatenated chunks or the concatenated chunks as a {@link Uint8Array}. + * + * @deprecated Use {@link ReadableStream.bytes} + */ + function readableStreamToBytes( + stream: ReadableStream, + ): Promise> | Uint8Array; + + /** + * Consume all data from a {@link ReadableStream} until it closes or errors. + * + * Concatenate the chunks into a single {@link Blob}. + * + * @param stream The stream to consume. + * @returns A promise that resolves with the concatenated chunks as a {@link Blob}. + * + * @deprecated Use {@link ReadableStream.blob} + */ + function readableStreamToBlob(stream: ReadableStream): Promise; + + /** + * Consume all data from a {@link ReadableStream} until it closes or errors. + * + * Concatenate the chunks into a single string. Chunks must be a TypedArray or an ArrayBuffer. If you need to support chunks of different types, consider {@link readableStreamToBlob}. + * + * @param stream The stream to consume. + * @returns A promise that resolves with the concatenated chunks as a {@link String}. + * + * @deprecated Use {@link ReadableStream.text} + */ + function readableStreamToText(stream: ReadableStream): Promise; + + /** + * Consume all data from a {@link ReadableStream} until it closes or errors. + * + * Concatenate the chunks into a single string and parse as JSON. Chunks must be a TypedArray or an ArrayBuffer. If you need to support chunks of different types, consider {@link readableStreamToBlob}. + * + * @param stream The stream to consume. + * @returns A promise that resolves with the concatenated chunks as a {@link String}. + * + * @deprecated Use {@link ReadableStream.json} + */ + function readableStreamToJSON(stream: ReadableStream): Promise; + interface BunMessageEvent { /** * @deprecated @@ -31,6 +84,9 @@ declare module "bun" { */ type Errorlike = ErrorLike; + /** @deprecated This is unused in Bun's types and may be removed in the future */ + type ShellFunction = (input: Uint8Array) => Uint8Array; + interface TLSOptions { /** * File path to a TLS key @@ -59,7 +115,7 @@ declare module "bun" { } /** @deprecated This type is unused in Bun's declarations and may be removed in the future */ - type ReadableIO = ReadableStream | number | undefined; + type ReadableIO = ReadableStream> | number | undefined; } declare namespace NodeJS { diff --git a/packages/bun-types/fetch.d.ts b/packages/bun-types/fetch.d.ts index bc8c26e569..ed1c2f8bef 100644 --- a/packages/bun-types/fetch.d.ts +++ b/packages/bun-types/fetch.d.ts @@ -1,19 +1,21 @@ /* - - This file does not declare any global types. - - That should only happen in [./globals.d.ts](./globals.d.ts) - so that our documentation generator can pick it up, as it - expects all globals to be declared in one file. - + * This file does not declare any global types. + * + * That should only happen in [./globals.d.ts](./globals.d.ts) + * so that our documentation generator can pick it up, as it + * expects all globals to be declared in one file. + * + * This may change in the future, which would be + * a nice thing as it would allow us to split up + * relevant types into their own files. */ - declare module "bun" { type HeadersInit = string[][] | Record> | Headers; type BodyInit = | ReadableStream | Bun.XMLHttpRequestBodyInit - | URLSearchParams + // Extras that Bun supports: + | AsyncIterable | AsyncGenerator | (() => AsyncGenerator); @@ -26,7 +28,7 @@ declare module "bun" { ? {} : Omit & { body?: Bun.BodyInit | null | undefined; - headers?: Bun.HeadersInit; + headers?: Bun.HeadersInit | undefined; }; interface BunHeadersOverride extends LibOrFallbackHeaders { diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 20d17e083c..ae8ab80d51 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -999,6 +999,7 @@ interface ArrayBuffer { * Read-only. The length of the ArrayBuffer (in bytes). */ readonly byteLength: number; + /** * Resize an ArrayBuffer in-place. */ @@ -1008,7 +1009,6 @@ interface ArrayBuffer { * Returns a section of an ArrayBuffer. */ slice(begin: number, end?: number): ArrayBuffer; - readonly [Symbol.toStringTag]: string; } interface SharedArrayBuffer { @@ -1284,7 +1284,7 @@ interface ImportMeta { * ) * ``` */ - readonly main: boolean; + main: boolean; /** Alias of `import.meta.dir`. Exists for Node.js compatibility */ dirname: string; @@ -1426,12 +1426,12 @@ interface Blob { /** * Returns a promise that resolves to the contents of the blob as a Uint8Array (array of bytes) its the same as `new Uint8Array(await blob.arrayBuffer())` */ - bytes(): Promise; + bytes(): Promise>; /** * Returns a readable stream of the blob's contents */ - stream(): ReadableStream; + stream(): ReadableStream>; } declare var Blob: Bun.__internal.UseLibDomIfAvailable< @@ -1506,14 +1506,14 @@ interface Uint8ArrayConstructor { alphabet?: "base64" | "base64url"; lastChunkHandling?: "loose" | "strict" | "stop-before-partial"; }, - ): Uint8Array; + ): Uint8Array; /** * Create a new Uint8Array from a hex encoded string * @param hex The hex encoded string to convert to a Uint8Array * @returns A new Uint8Array containing the decoded data */ - fromHex(hex: string): Uint8Array; + fromHex(hex: string): Uint8Array; } interface BroadcastChannel extends Bun.__internal.LibEmptyOrBroadcastChannel {} diff --git a/packages/bun-types/overrides.d.ts b/packages/bun-types/overrides.d.ts index 2bfb4d44da..f52de8acbf 100644 --- a/packages/bun-types/overrides.d.ts +++ b/packages/bun-types/overrides.d.ts @@ -6,14 +6,17 @@ declare module "stream/web" { * Consume a ReadableStream as text */ text(): Promise; + /** * Consume a ReadableStream as a Uint8Array */ - bytes(): Promise; + bytes(): Promise>; + /** * Consume a ReadableStream as JSON */ json(): Promise; + /** * Consume a ReadableStream as a Blob */ diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index 4ab5abba4a..44f250c476 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -10,10 +10,11 @@ }, "files": [ "./*.d.ts", - "docs/**/*.md", - "docs/*.md", - "CLAUDE.md", - "README.md" + "./vendor/**/*.d.ts", + "./docs/**/*.md", + "./docs/*.md", + "./CLAUDE.md", + "./README.md" ], "homepage": "https://bun.com", "dependencies": { @@ -23,8 +24,7 @@ "@types/react": "^19" }, "devDependencies": { - "@types/react": "^19", - "typescript": "^5.0.2" + "@types/react": "^19" }, "scripts": { "prebuild": "echo $(pwd)", diff --git a/packages/bun-types/s3.d.ts b/packages/bun-types/s3.d.ts index dcda85e682..0dd0f653d1 100644 --- a/packages/bun-types/s3.d.ts +++ b/packages/bun-types/s3.d.ts @@ -487,8 +487,8 @@ declare module "bun" { * // Process text chunk by chunk * } */ - readonly readable: ReadableStream; - stream(): ReadableStream; + readonly readable: ReadableStream>; + stream(): ReadableStream>; /** * The name or path of the file in the bucket. diff --git a/packages/bun-types/shell.d.ts b/packages/bun-types/shell.d.ts index 0659c2ff78..280e09fcf5 100644 --- a/packages/bun-types/shell.d.ts +++ b/packages/bun-types/shell.d.ts @@ -1,6 +1,4 @@ declare module "bun" { - type ShellFunction = (input: Uint8Array) => Uint8Array; - type ShellExpression = | { toString(): string } | Array @@ -294,7 +292,7 @@ declare module "bun" { * console.log(output.bytes()); // Uint8Array { byteLength: 6 } * ``` */ - bytes(): Uint8Array; + bytes(): Uint8Array; } interface ShellOutput { @@ -361,7 +359,7 @@ declare module "bun" { * console.log(output.bytes()); // Uint8Array { byteLength: 6 } * ``` */ - bytes(): Uint8Array; + bytes(): Uint8Array; /** * Read from stdout as a Blob diff --git a/packages/bun-types/sqlite.d.ts b/packages/bun-types/sqlite.d.ts index 94cbca0b95..0c79d22779 100644 --- a/packages/bun-types/sqlite.d.ts +++ b/packages/bun-types/sqlite.d.ts @@ -383,19 +383,28 @@ declare module "bun:sqlite" { * ]); * ``` */ - transaction(insideTransaction: (...args: any) => void): CallableFunction & { + transaction( + insideTransaction: (...args: A) => T, + ): { /** - * uses "BEGIN DEFERRED" + * Execute the transaction */ - deferred: (...args: any) => void; + (...args: A): T; + /** - * uses "BEGIN IMMEDIATE" + * Execute the transaction using "BEGIN DEFERRED" */ - immediate: (...args: any) => void; + deferred: (...args: A) => T; + /** - * uses "BEGIN EXCLUSIVE" + * Execute the transaction using "BEGIN IMMEDIATE" */ - exclusive: (...args: any) => void; + immediate: (...args: A) => T; + + /** + * Execute the transaction using "BEGIN EXCLUSIVE" + */ + exclusive: (...args: A) => T; }; /** @@ -664,7 +673,7 @@ declare module "bun:sqlite" { [Symbol.iterator](): IterableIterator; /** - * Execute the prepared statement. This returns `undefined`. + * Execute the prepared statement. * * @param params optional values to bind to the statement. If omitted, the statement is run with the last bound values or no parameters if there are none. * diff --git a/packages/bun-types/test-globals.d.ts b/packages/bun-types/test-globals.d.ts index b5c5d3ed4a..4f38635206 100644 --- a/packages/bun-types/test-globals.d.ts +++ b/packages/bun-types/test-globals.d.ts @@ -10,6 +10,7 @@ declare var test: typeof import("bun:test").test; declare var it: typeof import("bun:test").it; declare var describe: typeof import("bun:test").describe; declare var expect: typeof import("bun:test").expect; +declare var expectTypeOf: typeof import("bun:test").expectTypeOf; declare var beforeAll: typeof import("bun:test").beforeAll; declare var beforeEach: typeof import("bun:test").beforeEach; declare var afterEach: typeof import("bun:test").afterEach; diff --git a/packages/bun-types/test.d.ts b/packages/bun-types/test.d.ts index c02e72f1d7..e54cbb1648 100644 --- a/packages/bun-types/test.d.ts +++ b/packages/bun-types/test.d.ts @@ -56,6 +56,11 @@ declare module "bun:test" { * Restore the previous value of mocks. */ restore(): void; + + /** + * Reset all mock function state (calls, results, etc.) without restoring their original implementation. + */ + clearAllMocks(): void; }; /** @@ -1642,6 +1647,26 @@ declare module "bun:test" { */ toHaveReturnedTimes(times: number): void; + /** + * Ensures that a mock function has returned a specific value. + * This matcher uses deep equality, like toEqual(), and supports asymmetric matchers. + */ + toHaveReturnedWith(expected: unknown): void; + + /** + * Ensures that a mock function has returned a specific value on its last invocation. + * This matcher uses deep equality, like toEqual(), and supports asymmetric matchers. + */ + toHaveLastReturnedWith(expected: unknown): void; + + /** + * Ensures that a mock function has returned a specific value on the nth invocation. + * This matcher uses deep equality, like toEqual(), and supports asymmetric matchers. + * @param n The 1-based index of the function call + * @param expected The expected return value + */ + toHaveNthReturnedWith(n: number, expected: unknown): void; + /** * Ensures that a mock function is called. */ @@ -2182,4 +2207,6 @@ declare module "bun:test" { export type UnknownFunction = (...args: unknown[]) => unknown; } + + export const expectTypeOf: typeof import("./vendor/expect-type").expectTypeOf; } diff --git a/packages/bun-types/vendor/expect-type/branding.d.ts b/packages/bun-types/vendor/expect-type/branding.d.ts new file mode 100644 index 0000000000..e0dcb2dcdb --- /dev/null +++ b/packages/bun-types/vendor/expect-type/branding.d.ts @@ -0,0 +1,283 @@ +/* + Copyright 2024 Misha Kaletsky + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +*/ + +import type { ConstructorOverloadParameters, NumOverloads, OverloadsInfoUnion } from "./overloads"; +import type { + IsAny, + IsNever, + IsUnknown, + MutuallyExtends, + OptionalKeys, + ReadonlyKeys, + RequiredKeys, + UnionToTuple, +} from "./utils"; +/** + * Represents a deeply branded type. + * + * Recursively walk a type and replace it with a branded type related to the + * original. This is useful for equality-checking stricter than + * `A extends B ? B extends A ? true : false : false`, because it detects the + * difference between a few edge-case types that vanilla TypeScript + * doesn't by default: + * - `any` vs `unknown` + * - `{ readonly a: string }` vs `{ a: string }` + * - `{ a?: string }` vs `{ a: string | undefined }` + * + * __Note__: not very performant for complex types - this should only be used + * when you know you need it. If doing an equality check, it's almost always + * better to use {@linkcode StrictEqualUsingTSInternalIdenticalToOperator}. + */ +export type DeepBrand = + IsNever extends true + ? { + type: "never"; + } + : IsAny extends true + ? { + type: "any"; + } + : IsUnknown extends true + ? { + type: "unknown"; + } + : T extends string | number | boolean | symbol | bigint | null | undefined | void + ? { + type: "primitive"; + value: T; + } + : T extends new (...args: any[]) => any + ? { + type: "constructor"; + params: ConstructorOverloadParameters; + instance: DeepBrand any>>>; + } + : T extends (...args: infer P) => infer R + ? NumOverloads extends 1 + ? { + type: "function"; + params: DeepBrand

; + return: DeepBrand; + this: DeepBrand>; + props: DeepBrand>; + } + : UnionToTuple> extends infer OverloadsTuple + ? { + type: "overloads"; + overloads: { + [K in keyof OverloadsTuple]: DeepBrand; + }; + } + : never + : T extends any[] + ? { + type: "array"; + items: { + [K in keyof T]: T[K]; + }; + } + : { + type: "object"; + properties: { + [K in keyof T]: DeepBrand; + }; + readonly: ReadonlyKeys; + required: RequiredKeys; + optional: OptionalKeys; + constructorParams: DeepBrand>; + }; +/** + * Checks if two types are strictly equal using branding. + */ +export type StrictEqualUsingBranding = MutuallyExtends, DeepBrand>; diff --git a/packages/bun-types/vendor/expect-type/index.d.ts b/packages/bun-types/vendor/expect-type/index.d.ts new file mode 100644 index 0000000000..d12bbbc196 --- /dev/null +++ b/packages/bun-types/vendor/expect-type/index.d.ts @@ -0,0 +1,1207 @@ +/* + Copyright 2024 Misha Kaletsky + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +*/ + +import type { StrictEqualUsingBranding } from "./branding"; +import type { + ExpectAny, + ExpectArray, + ExpectBigInt, + ExpectBoolean, + ExpectFunction, + ExpectNever, + ExpectNull, + ExpectNullable, + ExpectNumber, + ExpectObject, + ExpectString, + ExpectSymbol, + ExpectUndefined, + ExpectUnknown, + ExpectVoid, + MismatchInfo, + Scolder, +} from "./messages"; +import type { + ConstructorOverloadParameters, + OverloadParameters, + OverloadReturnTypes, + OverloadsNarrowedByParameters, +} from "./overloads"; +import type { + AValue, + DeepPickMatchingProps, + Extends, + IsUnion, + MismatchArgs, + Not, + StrictEqualUsingTSInternalIdenticalToOperator, +} from "./utils"; +export * from "./branding"; +export * from "./messages"; +export * from "./overloads"; +export * from "./utils"; +/** + * Represents the positive assertion methods available for type checking in the + * {@linkcode expectTypeOf()} utility. + */ +export interface PositiveExpectTypeOf + extends BaseExpectTypeOf< + Actual, + { + positive: true; + branded: false; + } + > { + /** + * Similar to jest's `expect(...).toMatchObject(...)` but for types. + * Deeply "picks" the properties of the actual type based on the expected type, then performs a strict check to make sure the types match `Expected`. + * + * **Note**: optional properties on the {@linkcode Expected | expected type} are not allowed to be missing on the {@linkcode Actual | actual type}. + * + * @example + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchObjectType<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toMatchObjectType<{ a: number; c?: number }>() + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toMatchObjectType: < + Expected extends IsUnion extends true + ? "toMatchObject does not support union types" + : Not>> extends true + ? "toMatchObject only supports object types" + : StrictEqualUsingTSInternalIdenticalToOperator, Expected> extends true + ? unknown + : MismatchInfo, Expected>, + >( + ...MISMATCH: MismatchArgs< + StrictEqualUsingTSInternalIdenticalToOperator, Expected>, + true + > + ) => true; + /** + * Check if your type extends the expected type + * + * A less strict version of {@linkcode toEqualTypeOf | .toEqualTypeOf()} that allows for extra properties. + * This is roughly equivalent to an `extends` constraint in a function type argument. + * + * @example + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toExtend<{ a: number }>() + * + * expectTypeOf({ a: 1 }).not.toExtend<{ b: number }>() + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toExtend: extends true ? unknown : MismatchInfo>( + ...MISMATCH: MismatchArgs, true> + ) => true; + toEqualTypeOf: { + /** + * Uses TypeScript's internal technique to check for type "identicalness". + * + * It will check if the types are fully equal to each other. + * It will not fail if two objects have different values, but the same type. + * It will fail however if an object is missing a property. + * + * **_Unexpected failure_**? For a more permissive but less performant + * check that accommodates for equivalent intersection types, + * use {@linkcode branded | .branded.toEqualTypeOf()}. + * @see {@link https://github.com/mmkal/expect-type#why-is-my-assertion-failing | The documentation for details}. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 }) + * + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 }) + * ``` + * + * @param value - The value to compare against the expected type. + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + < + Expected extends StrictEqualUsingTSInternalIdenticalToOperator extends true + ? unknown + : MismatchInfo, + >( + value: Expected & AValue, // reason for `& AValue`: make sure this is only the selected overload when the end-user passes a value for an inferred typearg. The `Mismatch` type does match `AValue`. + ...MISMATCH: MismatchArgs, true> + ): true; + /** + * Uses TypeScript's internal technique to check for type "identicalness". + * + * It will check if the types are fully equal to each other. + * It will not fail if two objects have different values, but the same type. + * It will fail however if an object is missing a property. + * + * **_Unexpected failure_**? For a more permissive but less performant + * check that accommodates for equivalent intersection types, + * use {@linkcode branded | .branded.toEqualTypeOf()}. + * @see {@link https://github.com/mmkal/expect-type#why-is-my-assertion-failing | The documentation for details}. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 }) + * + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 }) + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + < + Expected extends StrictEqualUsingTSInternalIdenticalToOperator extends true + ? unknown + : MismatchInfo, + >( + ...MISMATCH: MismatchArgs, true> + ): true; + }; + /** + * @deprecated Use either {@linkcode toMatchObjectType} or {@linkcode toExtend} instead + * + * - Use {@linkcode toMatchObjectType} to perform a strict check on a subset of your type's keys + * - Use {@linkcode toExtend} to check if your type extends the expected type + */ + toMatchTypeOf: { + /** + * @deprecated Use either {@linkcode toMatchObjectType} or {@linkcode toExtend} instead + * + * - Use {@linkcode toMatchObjectType} to perform a strict check on a subset of your type's keys + * - Use {@linkcode toExtend} to check if your type extends the expected type + * + * A less strict version of {@linkcode toEqualTypeOf | .toEqualTypeOf()} + * that allows for extra properties. + * This is roughly equivalent to an `extends` constraint + * in a function type argument. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 2 }) + * ``` + * + * @param value - The value to compare against the expected type. + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + extends true ? unknown : MismatchInfo>( + value: Expected & AValue, // reason for `& AValue`: make sure this is only the selected overload when the end-user passes a value for an inferred typearg. The `Mismatch` type does match `AValue`. + ...MISMATCH: MismatchArgs, true> + ): true; + /** + * @deprecated Use either {@linkcode toMatchObjectType} or {@linkcode toExtend} instead + * + * - Use {@linkcode toMatchObjectType} to perform a strict check on a subset of your type's keys + * - Use {@linkcode toExtend} to check if your type extends the expected type + * + * A less strict version of {@linkcode toEqualTypeOf | .toEqualTypeOf()} + * that allows for extra properties. + * This is roughly equivalent to an `extends` constraint + * in a function type argument. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 2 }) + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + extends true ? unknown : MismatchInfo>( + ...MISMATCH: MismatchArgs, true> + ): true; + }; + /** + * Checks whether an object has a given property. + * + * @example + * check that properties exist + * ```ts + * const obj = { a: 1, b: '' } + * + * expectTypeOf(obj).toHaveProperty('a') + * + * expectTypeOf(obj).not.toHaveProperty('c') + * ``` + * + * @param key - The property key to check for. + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toHaveProperty: ( + key: KeyType, + ...MISMATCH: MismatchArgs, true> + ) => KeyType extends keyof Actual ? PositiveExpectTypeOf : true; + /** + * Inverts the result of the following assertions. + * + * @example + * ```ts + * expectTypeOf({ a: 1 }).not.toMatchTypeOf({ b: 1 }) + * ``` + */ + not: NegativeExpectTypeOf; + /** + * Intersection types can cause issues with + * {@linkcode toEqualTypeOf | .toEqualTypeOf()}: + * ```ts + * // ❌ The following line doesn't compile, even though the types are arguably the same. + * expectTypeOf<{ a: 1 } & { b: 2 }>().toEqualTypeOf<{ a: 1; b: 2 }>() + * ``` + * This helper works around this problem by using + * a more permissive but less performant check. + * + * __Note__: This comes at a performance cost, and can cause the compiler + * to 'give up' if used with excessively deep types, so use sparingly. + * + * @see {@link https://github.com/mmkal/expect-type/pull/21 | Reference} + */ + branded: { + /** + * Uses TypeScript's internal technique to check for type "identicalness". + * + * It will check if the types are fully equal to each other. + * It will not fail if two objects have different values, but the same type. + * It will fail however if an object is missing a property. + * + * **_Unexpected failure_**? For a more permissive but less performant + * check that accommodates for equivalent intersection types, + * use {@linkcode PositiveExpectTypeOf.branded | .branded.toEqualTypeOf()}. + * @see {@link https://github.com/mmkal/expect-type#why-is-my-assertion-failing | The documentation for details}. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 }) + * + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 }) + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toEqualTypeOf: < + Expected extends StrictEqualUsingBranding extends true + ? unknown + : MismatchInfo, + >( + ...MISMATCH: MismatchArgs, true> + ) => true; + }; +} +/** + * Represents the negative expectation type for the {@linkcode Actual} type. + */ +export interface NegativeExpectTypeOf + extends BaseExpectTypeOf< + Actual, + { + positive: false; + } + > { + /** + * Similar to jest's `expect(...).toMatchObject(...)` but for types. + * Deeply "picks" the properties of the actual type based on the expected type, then performs a strict check to make sure the types match `Expected`. + * + * **Note**: optional properties on the {@linkcode Expected | expected type} are not allowed to be missing on the {@linkcode Actual | actual type}. + * + * @example + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchObjectType<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toMatchObjectType<{ a: number; c?: number }>() + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toMatchObjectType: ( + ...MISMATCH: MismatchArgs< + StrictEqualUsingTSInternalIdenticalToOperator, Expected>, + false + > + ) => true; + /** + * Check if your type extends the expected type + * + * A less strict version of {@linkcode PositiveExpectTypeOf.toEqualTypeOf | .toEqualTypeOf()} that allows for extra properties. + * This is roughly equivalent to an `extends` constraint in a function type argument. + * + * @example + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toExtend<{ a: number }>()] + * + * expectTypeOf({ a: 1 }).not.toExtend<{ b: number }>() + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toExtend(...MISMATCH: MismatchArgs, false>): true; + toEqualTypeOf: { + /** + * Uses TypeScript's internal technique to check for type "identicalness". + * + * It will check if the types are fully equal to each other. + * It will not fail if two objects have different values, but the same type. + * It will fail however if an object is missing a property. + * + * **_Unexpected failure_**? For a more permissive but less performant + * check that accommodates for equivalent intersection types, + * use {@linkcode PositiveExpectTypeOf.branded | .branded.toEqualTypeOf()}. + * @see {@link https://github.com/mmkal/expect-type#why-is-my-assertion-failing | The documentation for details}. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 }) + * + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 }) + * ``` + * + * @param value - The value to compare against the expected type. + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + ( + value: Expected & AValue, + ...MISMATCH: MismatchArgs, false> + ): true; + /** + * Uses TypeScript's internal technique to check for type "identicalness". + * + * It will check if the types are fully equal to each other. + * It will not fail if two objects have different values, but the same type. + * It will fail however if an object is missing a property. + * + * **_Unexpected failure_**? For a more permissive but less performant + * check that accommodates for equivalent intersection types, + * use {@linkcode PositiveExpectTypeOf.branded | .branded.toEqualTypeOf()}. + * @see {@link https://github.com/mmkal/expect-type#why-is-my-assertion-failing | The documentation for details}. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>() + * + * expectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 }) + * + * expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 }) + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + (...MISMATCH: MismatchArgs, false>): true; + }; + /** + * @deprecated Use either {@linkcode toMatchObjectType} or {@linkcode toExtend} instead + * + * - Use {@linkcode toMatchObjectType} to perform a strict check on a subset of your type's keys + * - Use {@linkcode toExtend} to check if your type extends the expected type + */ + toMatchTypeOf: { + /** + * @deprecated Use either {@linkcode toMatchObjectType} or {@linkcode toExtend} instead + * + * - Use {@linkcode toMatchObjectType} to perform a strict check on a subset of your type's keys + * - Use {@linkcode toExtend} to check if your type extends the expected type + * + * A less strict version of + * {@linkcode PositiveExpectTypeOf.toEqualTypeOf | .toEqualTypeOf()} + * that allows for extra properties. + * This is roughly equivalent to an `extends` constraint + * in a function type argument. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 2 }) + * ``` + * + * @param value - The value to compare against the expected type. + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + ( + value: Expected & AValue, // reason for `& AValue`: make sure this is only the selected overload when the end-user passes a value for an inferred typearg. The `Mismatch` type does match `AValue`. + ...MISMATCH: MismatchArgs, false> + ): true; + /** + * @deprecated Use either {@linkcode toMatchObjectType} or {@linkcode toExtend} instead + * + * - Use {@linkcode toMatchObjectType} to perform a strict check on a subset of your type's keys + * - Use {@linkcode toExtend} to check if your type extends the expected type + * + * A less strict version of + * {@linkcode PositiveExpectTypeOf.toEqualTypeOf | .toEqualTypeOf()} + * that allows for extra properties. + * This is roughly equivalent to an `extends` constraint + * in a function type argument. + * + * @example + * Using generic type argument syntax + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf<{ a: number }>() + * ``` + * + * @example + * Using inferred type syntax by passing a value + * ```ts + * expectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 2 }) + * ``` + * + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + (...MISMATCH: MismatchArgs, false>): true; + }; + /** + * Checks whether an object has a given property. + * + * @example + * check that properties exist + * ```ts + * const obj = { a: 1, b: '' } + * + * expectTypeOf(obj).toHaveProperty('a') + * + * expectTypeOf(obj).not.toHaveProperty('c') + * ``` + * + * @param key - The property key to check for. + * @param MISMATCH - The mismatch arguments. + * @returns `true`. + */ + toHaveProperty: ( + key: KeyType, + ...MISMATCH: MismatchArgs, false> + ) => true; +} +/** + * Represents a conditional type that selects either + * {@linkcode PositiveExpectTypeOf} or {@linkcode NegativeExpectTypeOf} based + * on the value of the `positive` property in the {@linkcode Options} type. + */ +export type ExpectTypeOf< + Actual, + Options extends { + positive: boolean; + }, +> = Options["positive"] extends true ? PositiveExpectTypeOf : NegativeExpectTypeOf; +/** + * Represents the base interface for the + * {@linkcode expectTypeOf()} function. + * Provides a set of assertion methods to perform type checks on a value. + */ +export interface BaseExpectTypeOf< + Actual, + Options extends { + positive: boolean; + }, +> { + /** + * Checks whether the type of the value is `any`. + */ + toBeAny: Scolder, Options>; + /** + * Checks whether the type of the value is `unknown`. + */ + toBeUnknown: Scolder, Options>; + /** + * Checks whether the type of the value is `never`. + */ + toBeNever: Scolder, Options>; + /** + * Checks whether the type of the value is `function`. + */ + toBeFunction: Scolder, Options>; + /** + * Checks whether the type of the value is `object`. + */ + toBeObject: Scolder, Options>; + /** + * Checks whether the type of the value is an {@linkcode Array}. + */ + toBeArray: Scolder, Options>; + /** + * Checks whether the type of the value is `number`. + */ + toBeNumber: Scolder, Options>; + /** + * Checks whether the type of the value is `string`. + */ + toBeString: Scolder, Options>; + /** + * Checks whether the type of the value is `boolean`. + */ + toBeBoolean: Scolder, Options>; + /** + * Checks whether the type of the value is `void`. + */ + toBeVoid: Scolder, Options>; + /** + * Checks whether the type of the value is `symbol`. + */ + toBeSymbol: Scolder, Options>; + /** + * Checks whether the type of the value is `null`. + */ + toBeNull: Scolder, Options>; + /** + * Checks whether the type of the value is `undefined`. + */ + toBeUndefined: Scolder, Options>; + /** + * Checks whether the type of the value is `null` or `undefined`. + */ + toBeNullable: Scolder, Options>; + /** + * Transform that type of the value via a callback. + * + * @param fn - A callback that transforms the input value. Note that this function is not actually called - it's only used for type inference. + * @returns A new type which can be used for further assertions. + */ + map: (fn: (value: Actual) => T) => ExpectTypeOf; + /** + * Checks whether the type of the value is **`bigint`**. + * + * @example + * #### Distinguish between **`number`** and **`bigint`** + * + * ```ts + * import { expectTypeOf } from 'expect-type' + * + * const aVeryBigInteger = 10n ** 100n + * + * expectTypeOf(aVeryBigInteger).not.toBeNumber() + * + * expectTypeOf(aVeryBigInteger).toBeBigInt() + * ``` + * + * @since 1.1.0 + */ + toBeBigInt: Scolder, Options>; + /** + * Checks whether a function is callable with the given parameters. + * + * __Note__: You cannot negate this assertion with + * {@linkcode PositiveExpectTypeOf.not | .not}, you need to use + * `ts-expect-error` instead. + * + * @example + * ```ts + * const f = (a: number) => [a, a] + * + * expectTypeOf(f).toBeCallableWith(1) + * ``` + * + * __Known Limitation__: This assertion will likely fail if you try to use it + * with a generic function or an overload. + * @see {@link https://github.com/mmkal/expect-type/issues/50 | This issue} for an example and a workaround. + * + * @param args - The arguments to check for callability. + * @returns `true`. + */ + toBeCallableWith: Options["positive"] extends true + ? >( + ...args: Args + ) => ExpectTypeOf, Options> + : never; + /** + * Checks whether a class is constructible with the given parameters. + * + * @example + * ```ts + * expectTypeOf(Date).toBeConstructibleWith('1970') + * + * expectTypeOf(Date).toBeConstructibleWith(0) + * + * expectTypeOf(Date).toBeConstructibleWith(new Date()) + * + * expectTypeOf(Date).toBeConstructibleWith() + * ``` + * + * @param args - The arguments to check for constructibility. + * @returns `true`. + */ + toBeConstructibleWith: Options["positive"] extends true + ? >(...args: Args) => true + : never; + /** + * Equivalent to the {@linkcode Extract} utility type. + * Helps narrow down complex union types. + * + * @example + * ```ts + * type ResponsiveProp = T | T[] | { xs?: T; sm?: T; md?: T } + * + * interface CSSProperties { + * margin?: string + * padding?: string + * } + * + * function getResponsiveProp(_props: T): ResponsiveProp { + * return {} + * } + * + * const cssProperties: CSSProperties = { margin: '1px', padding: '2px' } + * + * expectTypeOf(getResponsiveProp(cssProperties)) + * .extract<{ xs?: any }>() // extracts the last type from a union + * .toEqualTypeOf<{ + * xs?: CSSProperties + * sm?: CSSProperties + * md?: CSSProperties + * }>() + * + * expectTypeOf(getResponsiveProp(cssProperties)) + * .extract() // extracts an array from a union + * .toEqualTypeOf() + * ``` + * + * __Note__: If no type is found in the union, it will return `never`. + * + * @param v - The type to extract from the union. + * @returns The type after extracting the type from the union. + */ + extract: (v?: V) => ExpectTypeOf, Options>; + /** + * Equivalent to the {@linkcode Exclude} utility type. + * Removes types from a union. + * + * @example + * ```ts + * type ResponsiveProp = T | T[] | { xs?: T; sm?: T; md?: T } + * + * interface CSSProperties { + * margin?: string + * padding?: string + * } + * + * function getResponsiveProp(_props: T): ResponsiveProp { + * return {} + * } + * + * const cssProperties: CSSProperties = { margin: '1px', padding: '2px' } + * + * expectTypeOf(getResponsiveProp(cssProperties)) + * .exclude() + * .exclude<{ xs?: unknown }>() // or just `.exclude()` + * .toEqualTypeOf() + * ``` + */ + exclude: (v?: V) => ExpectTypeOf, Options>; + /** + * Equivalent to the {@linkcode Pick} utility type. + * Helps select a subset of properties from an object type. + * + * @example + * ```ts + * interface Person { + * name: string + * age: number + * } + * + * expectTypeOf() + * .pick<'name'>() + * .toEqualTypeOf<{ name: string }>() + * ``` + * + * @param keyToPick - The property key to pick. + * @returns The type after picking the property. + */ + pick: (keyToPick?: KeyToPick) => ExpectTypeOf, Options>; + /** + * Equivalent to the {@linkcode Omit} utility type. + * Helps remove a subset of properties from an object type. + * + * @example + * ```ts + * interface Person { + * name: string + * age: number + * } + * + * expectTypeOf().omit<'name'>().toEqualTypeOf<{ age: number }>() + * ``` + * + * @param keyToOmit - The property key to omit. + * @returns The type after omitting the property. + */ + omit: )>( + keyToOmit?: KeyToOmit, + ) => ExpectTypeOf, Options>; + /** + * Extracts a certain function argument with `.parameter(number)` call to + * perform other assertions on it. + * + * @example + * ```ts + * function foo(a: number, b: string) { + * return [a, b] + * } + * + * expectTypeOf(foo).parameter(0).toBeNumber() + * + * expectTypeOf(foo).parameter(1).toBeString() + * ``` + * + * @param index - The index of the parameter to extract. + * @returns The extracted parameter type. + */ + parameter: (index: Index) => ExpectTypeOf[Index], Options>; + /** + * Equivalent to the {@linkcode Parameters} utility type. + * Extracts function parameters to perform assertions on its value. + * Parameters are returned as an array. + * + * @example + * ```ts + * function noParam() {} + * + * function hasParam(s: string) {} + * + * expectTypeOf(noParam).parameters.toEqualTypeOf<[]>() + * + * expectTypeOf(hasParam).parameters.toEqualTypeOf<[string]>() + * ``` + */ + parameters: ExpectTypeOf, Options>; + /** + * Equivalent to the {@linkcode ConstructorParameters} utility type. + * Extracts constructor parameters as an array of values and + * perform assertions on them with this method. + * + * For overloaded constructors it will return a union of all possible parameter-tuples. + * + * @example + * ```ts + * expectTypeOf(Date).constructorParameters.toEqualTypeOf< + * [] | [string | number | Date] + * >() + * ``` + */ + constructorParameters: ExpectTypeOf, Options>; + /** + * Equivalent to the {@linkcode ThisParameterType} utility type. + * Extracts the `this` parameter of a function to + * perform assertions on its value. + * + * @example + * ```ts + * function greet(this: { name: string }, message: string) { + * return `Hello ${this.name}, here's your message: ${message}` + * } + * + * expectTypeOf(greet).thisParameter.toEqualTypeOf<{ name: string }>() + * ``` + */ + thisParameter: ExpectTypeOf, Options>; + /** + * Equivalent to the {@linkcode InstanceType} utility type. + * Extracts the instance type of a class to perform assertions on. + * + * @example + * ```ts + * expectTypeOf(Date).instance.toHaveProperty('toISOString') + * ``` + */ + instance: Actual extends new (...args: any[]) => infer I ? ExpectTypeOf : never; + /** + * Equivalent to the {@linkcode ReturnType} utility type. + * Extracts the return type of a function. + * + * @example + * ```ts + * expectTypeOf(() => {}).returns.toBeVoid() + * + * expectTypeOf((a: number) => [a, a]).returns.toEqualTypeOf([1, 2]) + * ``` + */ + returns: Actual extends Function ? ExpectTypeOf, Options> : never; + /** + * Extracts resolved value of a Promise, + * so you can perform other assertions on it. + * + * @example + * ```ts + * async function asyncFunc() { + * return 123 + * } + * + * expectTypeOf(asyncFunc).returns.resolves.toBeNumber() + * + * expectTypeOf(Promise.resolve('string')).resolves.toBeString() + * ``` + * + * Type Equivalent: + * ```ts + * type Resolves = PromiseType extends PromiseLike + * ? ResolvedType + * : never + * ``` + */ + resolves: Actual extends PromiseLike ? ExpectTypeOf : never; + /** + * Extracts array item type to perform assertions on. + * + * @example + * ```ts + * expectTypeOf([1, 2, 3]).items.toEqualTypeOf() + * + * expectTypeOf([1, 2, 3]).items.not.toEqualTypeOf() + * ``` + * + * __Type Equivalent__: + * ```ts + * type Items = ArrayType extends ArrayLike + * ? ItemType + * : never + * ``` + */ + items: Actual extends ArrayLike ? ExpectTypeOf : never; + /** + * Extracts the type guarded by a function to perform assertions on. + * + * @example + * ```ts + * function isString(v: any): v is string { + * return typeof v === 'string' + * } + * + * expectTypeOf(isString).guards.toBeString() + * ``` + */ + guards: Actual extends (v: any, ...args: any[]) => v is infer T ? ExpectTypeOf : never; + /** + * Extracts the type asserted by a function to perform assertions on. + * + * @example + * ```ts + * function assertNumber(v: any): asserts v is number { + * if (typeof v !== 'number') + * throw new TypeError('Nope !') + * } + * + * expectTypeOf(assertNumber).asserts.toBeNumber() + * ``` + */ + asserts: Actual extends (v: any, ...args: any[]) => asserts v is infer T + ? unknown extends T + ? never + : ExpectTypeOf + : never; +} +/** + * Represents a function that allows asserting the expected type of a value. + */ +export type _ExpectTypeOf = { + /** + * Asserts the expected type of a value. + * + * @param actual - The actual value being asserted. + * @returns An object representing the expected type assertion. + */ + (actual: Actual): ExpectTypeOf< + Actual, + { + positive: true; + branded: false; + } + >; + /** + * Asserts the expected type of a value without providing an actual value. + * + * @returns An object representing the expected type assertion. + */ + (): ExpectTypeOf< + Actual, + { + positive: true; + branded: false; + } + >; +}; +/** + * Similar to Jest's `expect`, but with type-awareness. + * Gives you access to a number of type-matchers that let you make assertions about the + * form of a reference or generic type parameter. + * + * @example + * ```ts + * import { foo, bar } from '../foo' + * import { expectTypeOf } from 'expect-type' + * + * test('foo types', () => { + * // make sure `foo` has type { a: number } + * expectTypeOf(foo).toMatchTypeOf({ a: 1 }) + * expectTypeOf(foo).toHaveProperty('a').toBeNumber() + * + * // make sure `bar` is a function taking a string: + * expectTypeOf(bar).parameter(0).toBeString() + * expectTypeOf(bar).returns.not.toBeAny() + * }) + * ``` + * + * @description + * See the [full docs](https://npmjs.com/package/expect-type#documentation) for lots more examples. + */ +export declare const expectTypeOf: _ExpectTypeOf; diff --git a/packages/bun-types/vendor/expect-type/messages.d.ts b/packages/bun-types/vendor/expect-type/messages.d.ts new file mode 100644 index 0000000000..cc6b05f297 --- /dev/null +++ b/packages/bun-types/vendor/expect-type/messages.d.ts @@ -0,0 +1,395 @@ +/* + Copyright 2024 Misha Kaletsky + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +*/ + +import type { StrictEqualUsingBranding } from "./branding"; +import type { And, Extends, ExtendsExcludingAnyOrNever, IsAny, IsNever, IsUnknown, Not, UsefulKeys } from "./utils"; +/** + * Determines the printable type representation for a given type. + */ +export type PrintType = + IsUnknown extends true + ? "unknown" + : IsNever extends true + ? "never" + : IsAny extends true + ? never + : boolean extends T + ? "boolean" + : T extends boolean + ? `literal boolean: ${T}` + : string extends T + ? "string" + : T extends string + ? `literal string: ${T}` + : number extends T + ? "number" + : T extends number + ? `literal number: ${T}` + : bigint extends T + ? "bigint" + : T extends bigint + ? `literal bigint: ${T}` + : T extends null + ? "null" + : T extends undefined + ? "undefined" + : T extends (...args: any[]) => any + ? "function" + : "..."; +/** + * Helper for showing end-user a hint why their type assertion is failing. + * This swaps "leaf" types with a literal message about what the actual and + * expected types are. Needs to check for `Not>` because + * otherwise `LeafTypeOf` returns `never`, which extends everything 🤔 + */ +export type MismatchInfo = + And<[Extends, "...">, Not>]> extends true + ? And<[Extends, Extends]> extends true + ? Array[number], Extract[number]>> + : { + [K in UsefulKeys | UsefulKeys]: MismatchInfo< + K extends keyof Actual ? Actual[K] : never, + K extends keyof Expected ? Expected[K] : never + >; + } + : StrictEqualUsingBranding extends true + ? Actual + : `Expected: ${PrintType}, Actual: ${PrintType>}`; +/** + * @internal + */ +declare const inverted: unique symbol; +/** + * @internal + */ +type Inverted = { + [inverted]: T; +}; +/** + * @internal + */ +declare const expectNull: unique symbol; +export type ExpectNull = { + [expectNull]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectUndefined: unique symbol; +export type ExpectUndefined = { + [expectUndefined]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectNumber: unique symbol; +export type ExpectNumber = { + [expectNumber]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectString: unique symbol; +export type ExpectString = { + [expectString]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectBoolean: unique symbol; +export type ExpectBoolean = { + [expectBoolean]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectVoid: unique symbol; +export type ExpectVoid = { + [expectVoid]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectFunction: unique symbol; +export type ExpectFunction = { + [expectFunction]: T; + result: ExtendsExcludingAnyOrNever any>; +}; +/** + * @internal + */ +declare const expectObject: unique symbol; +export type ExpectObject = { + [expectObject]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectArray: unique symbol; +export type ExpectArray = { + [expectArray]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectSymbol: unique symbol; +export type ExpectSymbol = { + [expectSymbol]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * @internal + */ +declare const expectAny: unique symbol; +export type ExpectAny = { + [expectAny]: T; + result: IsAny; +}; +/** + * @internal + */ +declare const expectUnknown: unique symbol; +export type ExpectUnknown = { + [expectUnknown]: T; + result: IsUnknown; +}; +/** + * @internal + */ +declare const expectNever: unique symbol; +export type ExpectNever = { + [expectNever]: T; + result: IsNever; +}; +/** + * @internal + */ +declare const expectNullable: unique symbol; +export type ExpectNullable = { + [expectNullable]: T; + result: Not>>; +}; +/** + * @internal + */ +declare const expectBigInt: unique symbol; +export type ExpectBigInt = { + [expectBigInt]: T; + result: ExtendsExcludingAnyOrNever; +}; +/** + * Checks if the result of an expecter matches the specified options, and + * resolves to a fairly readable error message if not. + */ +export type Scolder< + Expecter extends { + result: boolean; + }, + Options extends { + positive: boolean; + }, +> = Expecter["result"] extends Options["positive"] + ? () => true + : Options["positive"] extends true + ? Expecter + : Inverted; +export {}; diff --git a/packages/bun-types/vendor/expect-type/overloads.d.ts b/packages/bun-types/vendor/expect-type/overloads.d.ts new file mode 100644 index 0000000000..ec14741e63 --- /dev/null +++ b/packages/bun-types/vendor/expect-type/overloads.d.ts @@ -0,0 +1,669 @@ +/* + Copyright 2024 Misha Kaletsky + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +*/ + +import type { + IsNever, + StrictEqualUsingTSInternalIdenticalToOperator, + UnionToIntersection, + UnionToTuple, +} from "./utils"; +/** + * The simple(ish) way to get overload info from a function + * {@linkcode FunctionType}. Recent versions of TypeScript will match any + * function against a generic 10-overload type, filling in slots with + * duplicates of the function. So, we can just match against a single type + * and get all the overloads. + * + * For older versions of TypeScript, we'll need to painstakingly do + * ten separate matches. + */ +export type TSPost53OverloadsInfoUnion = FunctionType extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + (...args: infer A6): infer R6; + (...args: infer A7): infer R7; + (...args: infer A8): infer R8; + (...args: infer A9): infer R9; + (...args: infer A10): infer R10; +} + ? + | ((...p: A1) => R1) + | ((...p: A2) => R2) + | ((...p: A3) => R3) + | ((...p: A4) => R4) + | ((...p: A5) => R5) + | ((...p: A6) => R6) + | ((...p: A7) => R7) + | ((...p: A8) => R8) + | ((...p: A9) => R9) + | ((...p: A10) => R10) + : never; +/** + * A function with `unknown` parameters and return type. + */ +export type UnknownFunction = (...args: unknown[]) => unknown; +/** + * `true` iff {@linkcode FunctionType} is + * equivalent to `(...args: unknown[]) => unknown`, + * which is what an overload variant looks like for a non-existent overload. + * This is useful because older versions of TypeScript end up with + * 9 "useless" overloads and one real one for parameterless/generic functions. + * + * @see {@link https://github.com/microsoft/TypeScript/issues/28867 | Related} + */ +export type IsUselessOverloadInfo = StrictEqualUsingTSInternalIdenticalToOperator< + FunctionType, + UnknownFunction +>; +/** + * Old versions of TypeScript can sometimes seem to refuse to separate out + * union members unless you put them each in a pointless tuple and add an + * extra `infer X` expression. There may be a better way to work around this + * problem, but since it's not a problem in newer versions of TypeScript, + * it's not a priority right now. + */ +export type Tuplify = Union extends infer X ? [X] : never; +/** + * For older versions of TypeScript, we need two separate workarounds + * to get overload info. First, we need need to use + * {@linkcode DecreasingOverloadsInfoUnion} to get the overload info for + * functions with 1-10 overloads. Then, we need to filter out the + * "useless" overloads that are present in older versions of TypeScript, + * for parameterless functions. To do this we use + * {@linkcode IsUselessOverloadInfo} to remove useless overloads. + * + * @see {@link https://github.com/microsoft/TypeScript/issues/28867 | Related} + */ +export type TSPre53OverloadsInfoUnion = + Tuplify> extends infer Tup + ? Tup extends [infer Fn] + ? IsUselessOverloadInfo extends true + ? never + : Fn + : never + : never; +/** + * For versions of TypeScript below 5.3, we need to check for 10 overloads, + * then 9, then 8, etc., to get a union of the overload variants. + */ +export type DecreasingOverloadsInfoUnion = F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + (...args: infer A6): infer R6; + (...args: infer A7): infer R7; + (...args: infer A8): infer R8; + (...args: infer A9): infer R9; + (...args: infer A10): infer R10; +} + ? + | ((...p: A1) => R1) + | ((...p: A2) => R2) + | ((...p: A3) => R3) + | ((...p: A4) => R4) + | ((...p: A5) => R5) + | ((...p: A6) => R6) + | ((...p: A7) => R7) + | ((...p: A8) => R8) + | ((...p: A9) => R9) + | ((...p: A10) => R10) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + (...args: infer A6): infer R6; + (...args: infer A7): infer R7; + (...args: infer A8): infer R8; + (...args: infer A9): infer R9; + } + ? + | ((...p: A1) => R1) + | ((...p: A2) => R2) + | ((...p: A3) => R3) + | ((...p: A4) => R4) + | ((...p: A5) => R5) + | ((...p: A6) => R6) + | ((...p: A7) => R7) + | ((...p: A8) => R8) + | ((...p: A9) => R9) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + (...args: infer A6): infer R6; + (...args: infer A7): infer R7; + (...args: infer A8): infer R8; + } + ? + | ((...p: A1) => R1) + | ((...p: A2) => R2) + | ((...p: A3) => R3) + | ((...p: A4) => R4) + | ((...p: A5) => R5) + | ((...p: A6) => R6) + | ((...p: A7) => R7) + | ((...p: A8) => R8) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + (...args: infer A6): infer R6; + (...args: infer A7): infer R7; + } + ? + | ((...p: A1) => R1) + | ((...p: A2) => R2) + | ((...p: A3) => R3) + | ((...p: A4) => R4) + | ((...p: A5) => R5) + | ((...p: A6) => R6) + | ((...p: A7) => R7) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + (...args: infer A6): infer R6; + } + ? + | ((...p: A1) => R1) + | ((...p: A2) => R2) + | ((...p: A3) => R3) + | ((...p: A4) => R4) + | ((...p: A5) => R5) + | ((...p: A6) => R6) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + (...args: infer A5): infer R5; + } + ? ((...p: A1) => R1) | ((...p: A2) => R2) | ((...p: A3) => R3) | ((...p: A4) => R4) | ((...p: A5) => R5) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + (...args: infer A4): infer R4; + } + ? ((...p: A1) => R1) | ((...p: A2) => R2) | ((...p: A3) => R3) | ((...p: A4) => R4) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + (...args: infer A3): infer R3; + } + ? ((...p: A1) => R1) | ((...p: A2) => R2) | ((...p: A3) => R3) + : F extends { + (...args: infer A1): infer R1; + (...args: infer A2): infer R2; + } + ? ((...p: A1) => R1) | ((...p: A2) => R2) + : F extends (...args: infer A1) => infer R1 + ? (...p: A1) => R1 + : never; +/** + * Get a union of overload variants for a function {@linkcode FunctionType}. + * Does a check for whether we can do the one-shot + * 10-overload matcher (which works for ts\>5.3), and if not, + * falls back to the more complicated utility. + */ +export type OverloadsInfoUnion = + IsNever 2>> extends true + ? TSPre53OverloadsInfoUnion + : TSPost53OverloadsInfoUnion; +/** + * Allows inferring any function using the `infer` keyword. + */ +export type InferFunctionType any> = FunctionType; +/** + * A union type of the parameters allowed for any + * overload of function {@linkcode FunctionType}. + */ +export type OverloadParameters = + OverloadsInfoUnion extends InferFunctionType ? Parameters : never; +/** + * A union type of the return types for any overload of + * function {@linkcode FunctionType}. + */ +export type OverloadReturnTypes = + OverloadsInfoUnion extends InferFunctionType ? ReturnType : never; +/** + * Takes an overload variants {@linkcode Union}, + * produced from {@linkcode OverloadsInfoUnion} and rejects + * the ones incompatible with parameters {@linkcode Args}. + */ +export type SelectOverloadsInfo = + Union extends InferFunctionType ? (Args extends Parameters ? Fn : never) : never; +/** + * Creates a new overload (an intersection type) from an existing one, + * which only includes variant(s) which can accept + * {@linkcode Args} as parameters. + */ +export type OverloadsNarrowedByParameters< + FunctionType, + Args extends OverloadParameters, +> = UnionToIntersection, Args>>; +/** + * The simple(ish) way to get overload info from a constructor + * {@linkcode ConstructorType}. Recent versions of TypeScript will match any + * constructor against a generic 10-overload type, filling in slots with + * duplicates of the constructor. So, we can just match against a single type + * and get all the overloads. + * + * For older versions of TypeScript, + * we'll need to painstakingly do ten separate matches. + */ +export type TSPost53ConstructorOverloadsInfoUnion = ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + new (...args: infer A6): infer R6; + new (...args: infer A7): infer R7; + new (...args: infer A8): infer R8; + new (...args: infer A9): infer R9; + new (...args: infer A10): infer R10; +} + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + | (new (...p: A6) => R6) + | (new (...p: A7) => R7) + | (new (...p: A8) => R8) + | (new (...p: A9) => R9) + | (new (...p: A10) => R10) + : never; +/** + * A constructor function with `unknown` parameters and return type. + */ +export type UnknownConstructor = new (...args: unknown[]) => unknown; +/** + * Same as {@linkcode IsUselessOverloadInfo}, but for constructors. + */ +export type IsUselessConstructorOverloadInfo = StrictEqualUsingTSInternalIdenticalToOperator< + FunctionType, + UnknownConstructor +>; +/** + * For older versions of TypeScript, we need two separate workarounds to + * get constructor overload info. First, we need need to use + * {@linkcode DecreasingConstructorOverloadsInfoUnion} to get the overload + * info for constructors with 1-10 overloads. Then, we need to filter out the + * "useless" overloads that are present in older versions of TypeScript, + * for parameterless constructors. To do this we use + * {@linkcode IsUselessConstructorOverloadInfo} to remove useless overloads. + * + * @see {@link https://github.com/microsoft/TypeScript/issues/28867 | Related} + */ +export type TSPre53ConstructorOverloadsInfoUnion = + Tuplify> extends infer Tup + ? Tup extends [infer Ctor] + ? IsUselessConstructorOverloadInfo extends true + ? never + : Ctor + : never + : never; +/** + * For versions of TypeScript below 5.3, we need to check for 10 overloads, + * then 9, then 8, etc., to get a union of the overload variants. + */ +export type DecreasingConstructorOverloadsInfoUnion = ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + new (...args: infer A6): infer R6; + new (...args: infer A7): infer R7; + new (...args: infer A8): infer R8; + new (...args: infer A9): infer R9; + new (...args: infer A10): infer R10; +} + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + | (new (...p: A6) => R6) + | (new (...p: A7) => R7) + | (new (...p: A8) => R8) + | (new (...p: A9) => R9) + | (new (...p: A10) => R10) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + new (...args: infer A6): infer R6; + new (...args: infer A7): infer R7; + new (...args: infer A8): infer R8; + new (...args: infer A9): infer R9; + } + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + | (new (...p: A6) => R6) + | (new (...p: A7) => R7) + | (new (...p: A8) => R8) + | (new (...p: A9) => R9) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + new (...args: infer A6): infer R6; + new (...args: infer A7): infer R7; + new (...args: infer A8): infer R8; + } + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + | (new (...p: A6) => R6) + | (new (...p: A7) => R7) + | (new (...p: A8) => R8) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + new (...args: infer A6): infer R6; + new (...args: infer A7): infer R7; + } + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + | (new (...p: A6) => R6) + | (new (...p: A7) => R7) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + new (...args: infer A6): infer R6; + } + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + | (new (...p: A6) => R6) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + new (...args: infer A5): infer R5; + } + ? + | (new (...p: A1) => R1) + | (new (...p: A2) => R2) + | (new (...p: A3) => R3) + | (new (...p: A4) => R4) + | (new (...p: A5) => R5) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + new (...args: infer A4): infer R4; + } + ? (new (...p: A1) => R1) | (new (...p: A2) => R2) | (new (...p: A3) => R3) | (new (...p: A4) => R4) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + new (...args: infer A3): infer R3; + } + ? (new (...p: A1) => R1) | (new (...p: A2) => R2) | (new (...p: A3) => R3) + : ConstructorType extends { + new (...args: infer A1): infer R1; + new (...args: infer A2): infer R2; + } + ? (new (...p: A1) => R1) | (new (...p: A2) => R2) + : ConstructorType extends new (...args: infer A1) => infer R1 + ? new (...p: A1) => R1 + : never; +/** + * Get a union of overload variants for a constructor + * {@linkcode ConstructorType}. Does a check for whether we can do the + * one-shot 10-overload matcher (which works for ts\>5.3), and if not, + * falls back to the more complicated utility. + */ +export type ConstructorOverloadsUnion = + IsNever any>> extends true + ? TSPre53ConstructorOverloadsInfoUnion + : TSPost53ConstructorOverloadsInfoUnion; +/** + * Allows inferring any constructor using the `infer` keyword. + */ +export type InferConstructor any> = ConstructorType; +/** + * A union type of the parameters allowed for any overload + * of constructor {@linkcode ConstructorType}. + */ +export type ConstructorOverloadParameters = + ConstructorOverloadsUnion extends InferConstructor ? ConstructorParameters : never; +/** + * Calculates the number of overloads for a given function type. + */ +export type NumOverloads = UnionToTuple>["length"]; diff --git a/packages/bun-types/vendor/expect-type/utils.d.ts b/packages/bun-types/vendor/expect-type/utils.d.ts new file mode 100644 index 0000000000..56cc074159 --- /dev/null +++ b/packages/bun-types/vendor/expect-type/utils.d.ts @@ -0,0 +1,431 @@ +/* + Copyright 2024 Misha Kaletsky + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +*/ + +/** + * Negates a boolean type. + */ +export type Not = T extends true ? false : true; +/** + * Returns `true` if at least one of the types in the + * {@linkcode Types} array is `true`, otherwise returns `false`. + */ +export type Or = Types[number] extends false ? false : true; +/** + * Checks if all the boolean types in the {@linkcode Types} array are `true`. + */ +export type And = Types[number] extends true ? true : false; +/** + * Represents an equality type that returns {@linkcode Right} if + * {@linkcode Left} is `true`, + * otherwise returns the negation of {@linkcode Right}. + */ +export type Eq = Left extends true ? Right : Not; +/** + * Represents the exclusive OR operation on a tuple of boolean types. + * Returns `true` if exactly one of the boolean types is `true`, + * otherwise returns `false`. + */ +export type Xor = Not>; +/** + * @internal + */ +declare const secret: unique symbol; +/** + * @internal + */ +type Secret = typeof secret; +/** + * Checks if the given type is `never`. + */ +export type IsNever = [T] extends [never] ? true : false; +/** + * Checks if the given type is `any`. + */ +export type IsAny = [T] extends [Secret] ? Not> : false; +/** + * Determines if the given type is `unknown`. + */ +export type IsUnknown = [unknown] extends [T] ? Not> : false; +/** + * Determines if a type is either `never` or `any`. + */ +export type IsNeverOrAny = Or<[IsNever, IsAny]>; +/** + * Subjective "useful" keys from a type. For objects it's just `keyof` but for + * tuples/arrays it's the number keys. + * + * @example + * ```ts + * UsefulKeys<{ a: 1; b: 2 }> // 'a' | 'b' + * + * UsefulKeys<['a', 'b']> // '0' | '1' + * + * UsefulKeys // number + * ``` + */ +export type UsefulKeys = T extends any[] + ? { + [K in keyof T]: K; + }[number] + : keyof T; +/** + * Extracts the keys from a type that are required (not optional). + */ +export type RequiredKeys = Extract< + { + [K in keyof T]-?: {} extends Pick ? never : K; + }[keyof T], + keyof T +>; +/** + * Gets the keys of an object type that are optional. + */ +export type OptionalKeys = Exclude>; +/** + * Extracts the keys from a type that are not `readonly`. + */ +export type ReadonlyKeys = Extract< + { + [K in keyof T]-?: ReadonlyEquivalent< + { + [_K in K]: T[K]; + }, + { + -readonly [_K in K]: T[K]; + } + > extends true + ? never + : K; + }[keyof T], + keyof T +>; +/** + * Determines if two types, are equivalent in a `readonly` manner. + * + * @internal + */ +type ReadonlyEquivalent = Extends<() => T extends X ? true : false, () => T extends Y ? true : false>; +/** + * Checks if one type extends another. Note: this is not quite the same as `Left extends Right` because: + * 1. If either type is `never`, the result is `true` iff the other type is also `never`. + * 2. Types are wrapped in a 1-tuple so that union types are not distributed - instead we consider `string | number` to _not_ extend `number`. If we used `Left extends Right` directly you would get `Extends` => `false | true` => `boolean`. + */ +export type Extends = IsNever extends true ? IsNever : [Left] extends [Right] ? true : false; +/** + * Checks if the {@linkcode Left} type extends the {@linkcode Right} type, + * excluding `any` or `never`. + */ +export type ExtendsExcludingAnyOrNever = IsAny extends true ? IsAny : Extends; +/** + * Checks if two types are strictly equal using + * the TypeScript internal identical-to operator. + * + * @see {@link https://github.com/microsoft/TypeScript/issues/55188#issuecomment-1656328122 | much history} + */ +export type StrictEqualUsingTSInternalIdenticalToOperator = + (() => T extends (L & T) | T ? true : false) extends () => T extends (R & T) | T ? true : false + ? IsNever extends IsNever + ? true + : false + : false; +/** + * Checks that {@linkcode Left} and {@linkcode Right} extend each other. + * Not quite the same as an equality check since `any` can make it resolve + * to `true`. So should only be used when {@linkcode Left} and + * {@linkcode Right} are known to avoid `any`. + */ +export type MutuallyExtends = And<[Extends, Extends]>; +/** + * @internal + */ +declare const mismatch: unique symbol; +/** + * @internal + */ +type Mismatch = { + [mismatch]: "mismatch"; +}; +/** + * A type which should match anything passed as a value but *doesn't* + * match {@linkcode Mismatch}. It helps TypeScript select the right overload + * for {@linkcode PositiveExpectTypeOf.toEqualTypeOf | .toEqualTypeOf()} and + * {@linkcode PositiveExpectTypeOf.toMatchTypeOf | .toMatchTypeOf()}. + * + * @internal + */ +declare const avalue: unique symbol; +/** + * Represents a value that can be of various types. + */ +export type AValue = + | { + [avalue]?: undefined; + } + | string + | number + | boolean + | symbol + | bigint + | null + | undefined + | void; +/** + * Represents the type of mismatched arguments between + * the actual result and the expected result. + * + * If {@linkcode ActualResult} and {@linkcode ExpectedResult} are equivalent, + * the type resolves to an empty tuple `[]`, indicating no mismatch. + * If they are not equivalent, it resolves to a tuple containing the element + * {@linkcode Mismatch}, signifying a discrepancy between + * the expected and actual results. + */ +export type MismatchArgs = + Eq extends true ? [] : [Mismatch]; +/** + * Represents the options for the {@linkcode ExpectTypeOf} function. + */ +export interface ExpectTypeOfOptions { + positive: boolean; + branded: boolean; +} +/** + * Convert a union to an intersection. + * `A | B | C` -\> `A & B & C` + */ +export type UnionToIntersection = (Union extends any ? (distributedUnion: Union) => void : never) extends ( + mergedIntersection: infer Intersection, +) => void + ? Intersection + : never; +/** + * Get the last element of a union. + * First, converts to a union of `() => T` functions, + * then uses {@linkcode UnionToIntersection} to get the last one. + */ +export type LastOf = + UnionToIntersection Union : never> extends () => infer R ? R : never; +/** + * Intermediate type for {@linkcode UnionToTuple} which pushes the + * "last" union member to the end of a tuple, and recursively prepends + * the remainder of the union. + */ +export type TuplifyUnion> = + IsNever extends true ? [] : [...TuplifyUnion>, LastElement]; +/** + * Convert a union like `1 | 2 | 3` to a tuple like `[1, 2, 3]`. + */ +export type UnionToTuple = TuplifyUnion; +export type IsTuple = Or<[Extends, Extends]>; +export type IsUnion = Not["length"], 1>>; +/** + * A recursive version of `Pick` that selects properties from the left type that are present in the right type. + * The "leaf" types from `Left` are used - only the keys of `Right` are considered. + * + * @example + * ```ts + * const user = {email: 'a@b.com', name: 'John Doe', address: {street: '123 2nd St', city: 'New York', zip: '10001', state: 'NY', country: 'USA'}} + * + * type Result = DeepPickMatchingProps // {name: string, address: {city: string}} + * ``` + */ +export type DeepPickMatchingProps = + Left extends Record + ? Pick< + { + [K in keyof Left]: K extends keyof Right ? DeepPickMatchingProps : never; + }, + Extract + > + : Left; +export {}; diff --git a/packages/bun-usockets/certdata.txt b/packages/bun-usockets/certdata.txt index 1ed5a248b5..aeedd56c53 100644 --- a/packages/bun-usockets/certdata.txt +++ b/packages/bun-usockets/certdata.txt @@ -200,7 +200,7 @@ END CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\013\004\000\000\000\000\001\025\113\132\303\224 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -366,141 +366,7 @@ END CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\004\070\143\336\370 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE - -# -# Certificate "Baltimore CyberTrust Root" -# -# Issuer: CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE -# Serial Number: 33554617 (0x20000b9) -# Subject: CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE -# Not Valid Before: Fri May 12 18:46:00 2000 -# Not Valid After : Mon May 12 23:59:00 2025 -# Fingerprint (SHA-256): 16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB -# Fingerprint (SHA1): D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 -CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Baltimore CyberTrust Root" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\132\061\013\060\011\006\003\125\004\006\023\002\111\105\061 -\022\060\020\006\003\125\004\012\023\011\102\141\154\164\151\155 -\157\162\145\061\023\060\021\006\003\125\004\013\023\012\103\171 -\142\145\162\124\162\165\163\164\061\042\060\040\006\003\125\004 -\003\023\031\102\141\154\164\151\155\157\162\145\040\103\171\142 -\145\162\124\162\165\163\164\040\122\157\157\164 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\132\061\013\060\011\006\003\125\004\006\023\002\111\105\061 -\022\060\020\006\003\125\004\012\023\011\102\141\154\164\151\155 -\157\162\145\061\023\060\021\006\003\125\004\013\023\012\103\171 -\142\145\162\124\162\165\163\164\061\042\060\040\006\003\125\004 -\003\023\031\102\141\154\164\151\155\157\162\145\040\103\171\142 -\145\162\124\162\165\163\164\040\122\157\157\164 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\004\002\000\000\271 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\003\167\060\202\002\137\240\003\002\001\002\002\004\002 -\000\000\271\060\015\006\011\052\206\110\206\367\015\001\001\005 -\005\000\060\132\061\013\060\011\006\003\125\004\006\023\002\111 -\105\061\022\060\020\006\003\125\004\012\023\011\102\141\154\164 -\151\155\157\162\145\061\023\060\021\006\003\125\004\013\023\012 -\103\171\142\145\162\124\162\165\163\164\061\042\060\040\006\003 -\125\004\003\023\031\102\141\154\164\151\155\157\162\145\040\103 -\171\142\145\162\124\162\165\163\164\040\122\157\157\164\060\036 -\027\015\060\060\060\065\061\062\061\070\064\066\060\060\132\027 -\015\062\065\060\065\061\062\062\063\065\071\060\060\132\060\132 -\061\013\060\011\006\003\125\004\006\023\002\111\105\061\022\060 -\020\006\003\125\004\012\023\011\102\141\154\164\151\155\157\162 -\145\061\023\060\021\006\003\125\004\013\023\012\103\171\142\145 -\162\124\162\165\163\164\061\042\060\040\006\003\125\004\003\023 -\031\102\141\154\164\151\155\157\162\145\040\103\171\142\145\162 -\124\162\165\163\164\040\122\157\157\164\060\202\001\042\060\015 -\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001 -\017\000\060\202\001\012\002\202\001\001\000\243\004\273\042\253 -\230\075\127\350\046\162\232\265\171\324\051\342\341\350\225\200 -\261\260\343\133\216\053\051\232\144\337\241\135\355\260\011\005 -\155\333\050\056\316\142\242\142\376\264\210\332\022\353\070\353 -\041\235\300\101\053\001\122\173\210\167\323\034\217\307\272\271 -\210\265\152\011\347\163\350\021\100\247\321\314\312\142\215\055 -\345\217\013\246\120\322\250\120\303\050\352\365\253\045\207\212 -\232\226\034\251\147\270\077\014\325\367\371\122\023\057\302\033 -\325\160\160\360\217\300\022\312\006\313\232\341\331\312\063\172 -\167\326\370\354\271\361\150\104\102\110\023\322\300\302\244\256 -\136\140\376\266\246\005\374\264\335\007\131\002\324\131\030\230 -\143\365\245\143\340\220\014\175\135\262\006\172\363\205\352\353 -\324\003\256\136\204\076\137\377\025\355\151\274\371\071\066\162 -\165\317\167\122\115\363\311\220\054\271\075\345\311\043\123\077 -\037\044\230\041\134\007\231\051\275\306\072\354\347\156\206\072 -\153\227\164\143\063\275\150\030\061\360\170\215\166\277\374\236 -\216\135\052\206\247\115\220\334\047\032\071\002\003\001\000\001 -\243\105\060\103\060\035\006\003\125\035\016\004\026\004\024\345 -\235\131\060\202\107\130\314\254\372\010\124\066\206\173\072\265 -\004\115\360\060\022\006\003\125\035\023\001\001\377\004\010\060 -\006\001\001\377\002\001\003\060\016\006\003\125\035\017\001\001 -\377\004\004\003\002\001\006\060\015\006\011\052\206\110\206\367 -\015\001\001\005\005\000\003\202\001\001\000\205\014\135\216\344 -\157\121\150\102\005\240\335\273\117\047\045\204\003\275\367\144 -\375\055\327\060\343\244\020\027\353\332\051\051\266\171\077\166 -\366\031\023\043\270\020\012\371\130\244\324\141\160\275\004\141 -\152\022\212\027\325\012\275\305\274\060\174\326\351\014\045\215 -\206\100\117\354\314\243\176\070\306\067\021\117\355\335\150\061 -\216\114\322\263\001\164\356\276\165\136\007\110\032\177\160\377 -\026\134\204\300\171\205\270\005\375\177\276\145\021\243\017\300 -\002\264\370\122\067\071\004\325\251\061\172\030\277\240\052\364 -\022\231\367\243\105\202\343\074\136\365\235\236\265\310\236\174 -\056\310\244\236\116\010\024\113\155\375\160\155\153\032\143\275 -\144\346\037\267\316\360\362\237\056\273\033\267\362\120\210\163 -\222\302\342\343\026\215\232\062\002\253\216\030\335\351\020\021 -\356\176\065\253\220\257\076\060\224\172\320\063\075\247\145\017 -\365\374\216\236\142\317\107\104\054\001\135\273\035\265\062\322 -\107\322\070\056\320\376\201\334\062\152\036\265\356\074\325\374 -\347\201\035\031\303\044\102\352\143\071\251 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE - -# Trust for "Baltimore CyberTrust Root" -# Issuer: CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE -# Serial Number: 33554617 (0x20000b9) -# Subject: CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE -# Not Valid Before: Fri May 12 18:46:00 2000 -# Not Valid After : Mon May 12 23:59:00 2025 -# Fingerprint (SHA-256): 16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB -# Fingerprint (SHA1): D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 -CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Baltimore CyberTrust Root" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\324\336\040\320\136\146\374\123\376\032\120\210\054\170\333\050 -\122\312\344\164 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\254\266\224\245\234\027\340\327\221\122\233\261\227\006\246\344 -END -CKA_ISSUER MULTILINE_OCTAL -\060\132\061\013\060\011\006\003\125\004\006\023\002\111\105\061 -\022\060\020\006\003\125\004\012\023\011\102\141\154\164\151\155 -\157\162\145\061\023\060\021\006\003\125\004\013\023\012\103\171 -\142\145\162\124\162\165\163\164\061\042\060\040\006\003\125\004 -\003\023\031\102\141\154\164\151\155\157\162\145\040\103\171\142 -\145\162\124\162\165\163\164\040\122\157\157\164 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\004\002\000\000\271 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -946,7 +812,7 @@ END CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\001\001 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -1452,7 +1318,7 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\020\120\224\154\354\030\352\325\234\115\325\227\357\165\217 \240\255 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -1598,8 +1464,8 @@ END CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\001\000 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -1745,8 +1611,8 @@ END CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\001\000 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -3323,9 +3189,13 @@ CKA_VALUE MULTILINE_OCTAL \201\370\021\234 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Tue Apr 15 23:59:59 2025 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\065\060\064\061\065\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + # Trust for "ePKI Root Certification Authority" # Issuer: OU=ePKI Root Certification Authority,O="Chunghwa Telecom Co., Ltd.",C=TW # Serial Number:15:c8:bd:65:47:5c:af:b8:97:00:5e:e4:06:d2:bc:9d @@ -25971,6 +25841,576 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +# +# Certificate "TrustAsia SMIME ECC Root CA" +# +# Issuer: CN=TrustAsia SMIME ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:5a:c2:f8:29:4f:e3:7d:c5:5e:1d:18:6f:3b:93:20:1f:ff:7b:ba:2d +# Subject: CN=TrustAsia SMIME ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:41:59 2024 +# Not Valid After : Sun May 15 05:41:58 2044 +# Fingerprint (SHA-256): 43:64:72:C1:00:9A:32:5C:54:F1:A5:BB:B5:46:8A:7B:AE:EC:CB:E0:5D:E5:F0:99:CB:70:D3:FE:41:E1:3C:16 +# Fingerprint (SHA1): 8C:0D:AA:FE:13:FA:59:F2:DB:9D:0C:97:DA:12:A2:45:1A:02:13:54 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia SMIME ECC Root CA" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023 +\033\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105 +\040\105\103\103\040\122\157\157\164\040\103\101 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023 +\033\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105 +\040\105\103\103\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\132\302\370\051\117\343\175\305\136\035\030\157\073\223 +\040\037\377\173\272\055 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\002\066\060\202\001\273\240\003\002\001\002\002\024\132 +\302\370\051\117\343\175\305\136\035\030\157\073\223\040\037\377 +\173\272\055\060\012\006\010\052\206\110\316\075\004\003\003\060 +\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061\045 +\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101\163 +\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163\054 +\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023\033 +\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105\040 +\105\103\103\040\122\157\157\164\040\103\101\060\036\027\015\062 +\064\060\065\061\065\060\065\064\061\065\071\132\027\015\064\064 +\060\065\061\065\060\065\064\061\065\070\132\060\132\061\013\060 +\011\006\003\125\004\006\023\002\103\116\061\045\060\043\006\003 +\125\004\012\023\034\124\162\165\163\164\101\163\151\141\040\124 +\145\143\150\156\157\154\157\147\151\145\163\054\040\111\156\143 +\056\061\044\060\042\006\003\125\004\003\023\033\124\162\165\163 +\164\101\163\151\141\040\123\115\111\115\105\040\105\103\103\040 +\122\157\157\164\040\103\101\060\166\060\020\006\007\052\206\110 +\316\075\002\001\006\005\053\201\004\000\042\003\142\000\004\315 +\331\373\047\275\151\354\206\311\220\103\261\160\027\224\247\311 +\167\043\072\077\043\145\323\034\243\035\036\102\124\040\353\320 +\102\273\131\271\213\254\362\206\215\113\216\035\252\226\042\043 +\071\166\155\222\233\353\042\313\172\103\242\163\375\163\113\302 +\045\017\052\261\151\306\377\105\337\251\074\225\200\273\251\036 +\112\223\057\354\034\035\210\364\021\222\067\237\067\230\162\243 +\102\060\100\060\017\006\003\125\035\023\001\001\377\004\005\060 +\003\001\001\377\060\035\006\003\125\035\016\004\026\004\024\061 +\147\346\162\262\015\346\042\240\254\317\176\042\247\131\062\343 +\146\043\245\060\016\006\003\125\035\017\001\001\377\004\004\003 +\002\001\006\060\012\006\010\052\206\110\316\075\004\003\003\003 +\151\000\060\146\002\061\000\335\072\114\215\244\306\177\355\275 +\245\306\117\076\375\061\113\050\326\212\126\337\145\026\167\207 +\115\373\272\062\010\201\340\236\063\110\213\237\224\206\357\001 +\053\224\346\214\326\324\216\002\061\000\237\201\234\260\046\375 +\053\326\362\365\161\204\236\250\307\212\214\326\130\021\122\265 +\270\004\313\314\161\165\143\342\306\031\070\331\155\154\031\161 +\244\026\031\041\223\272\006\104\050\154 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "TrustAsia SMIME ECC Root CA" +# Issuer: CN=TrustAsia SMIME ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:5a:c2:f8:29:4f:e3:7d:c5:5e:1d:18:6f:3b:93:20:1f:ff:7b:ba:2d +# Subject: CN=TrustAsia SMIME ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:41:59 2024 +# Not Valid After : Sun May 15 05:41:58 2044 +# Fingerprint (SHA-256): 43:64:72:C1:00:9A:32:5C:54:F1:A5:BB:B5:46:8A:7B:AE:EC:CB:E0:5D:E5:F0:99:CB:70:D3:FE:41:E1:3C:16 +# Fingerprint (SHA1): 8C:0D:AA:FE:13:FA:59:F2:DB:9D:0C:97:DA:12:A2:45:1A:02:13:54 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia SMIME ECC Root CA" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\214\015\252\376\023\372\131\362\333\235\014\227\332\022\242\105 +\032\002\023\124 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\225\175\377\225\115\114\152\373\215\014\017\317\102\333\357\040 +END +CKA_ISSUER MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023 +\033\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105 +\040\105\103\103\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\132\302\370\051\117\343\175\305\136\035\030\157\073\223 +\040\037\377\173\272\055 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "TrustAsia SMIME RSA Root CA" +# +# Issuer: CN=TrustAsia SMIME RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:5a:ee:71:df:de:0c:57:85:b5:bb:36:22:d7:b8:76:46:02:73:ca:ff +# Subject: CN=TrustAsia SMIME RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:42:01 2024 +# Not Valid After : Sun May 15 05:42:00 2044 +# Fingerprint (SHA-256): C7:79:6B:EB:62:C1:01:BB:14:3D:26:2A:7C:96:A0:C6:16:81:83:22:3E:F5:0D:69:96:32:D8:6E:03:B8:CC:9B +# Fingerprint (SHA1): 8C:69:21:7C:CE:49:73:36:5A:5C:EF:2B:B0:86:97:50:E3:E3:33:65 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia SMIME RSA Root CA" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023 +\033\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105 +\040\122\123\101\040\122\157\157\164\040\103\101 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023 +\033\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105 +\040\122\123\101\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\132\356\161\337\336\014\127\205\265\273\066\042\327\270 +\166\106\002\163\312\377 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\005\204\060\202\003\154\240\003\002\001\002\002\024\132 +\356\161\337\336\014\127\205\265\273\066\042\327\270\166\106\002 +\163\312\377\060\015\006\011\052\206\110\206\367\015\001\001\014 +\005\000\060\132\061\013\060\011\006\003\125\004\006\023\002\103 +\116\061\045\060\043\006\003\125\004\012\023\034\124\162\165\163 +\164\101\163\151\141\040\124\145\143\150\156\157\154\157\147\151 +\145\163\054\040\111\156\143\056\061\044\060\042\006\003\125\004 +\003\023\033\124\162\165\163\164\101\163\151\141\040\123\115\111 +\115\105\040\122\123\101\040\122\157\157\164\040\103\101\060\036 +\027\015\062\064\060\065\061\065\060\065\064\062\060\061\132\027 +\015\064\064\060\065\061\065\060\065\064\062\060\060\132\060\132 +\061\013\060\011\006\003\125\004\006\023\002\103\116\061\045\060 +\043\006\003\125\004\012\023\034\124\162\165\163\164\101\163\151 +\141\040\124\145\143\150\156\157\154\157\147\151\145\163\054\040 +\111\156\143\056\061\044\060\042\006\003\125\004\003\023\033\124 +\162\165\163\164\101\163\151\141\040\123\115\111\115\105\040\122 +\123\101\040\122\157\157\164\040\103\101\060\202\002\042\060\015 +\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\002 +\017\000\060\202\002\012\002\202\002\001\000\230\225\234\255\074 +\131\163\323\223\166\246\110\124\246\034\210\162\114\115\341\202 +\377\032\023\037\120\336\214\331\220\102\321\274\231\323\067\243 +\327\161\072\312\335\136\033\220\141\102\156\217\100\001\163\175 +\037\061\272\324\035\156\004\322\252\220\204\112\063\012\104\237 +\132\031\037\264\156\055\150\374\257\300\237\112\020\022\277\076 +\202\302\202\260\057\347\220\157\220\144\020\203\354\354\066\224 +\014\174\117\340\002\015\075\207\171\102\115\000\345\060\256\160 +\037\025\375\372\317\122\045\066\115\171\040\273\361\020\230\340 +\140\207\311\365\170\014\042\355\002\346\021\154\361\233\132\221 +\021\164\206\320\376\170\222\226\004\303\230\357\306\160\257\251 +\220\252\026\366\042\355\330\372\106\050\161\342\311\010\300\120 +\274\166\243\272\055\226\362\021\371\244\275\020\126\370\047\155 +\053\113\144\210\334\027\135\317\000\010\212\222\256\032\314\022 +\327\337\360\020\050\363\315\072\352\072\022\214\033\347\141\011 +\103\152\344\070\351\376\164\071\333\315\012\073\303\117\123\326 +\256\161\325\070\203\207\037\316\347\114\363\021\125\207\337\267 +\257\367\353\032\206\020\155\250\355\110\335\062\320\333\252\052 +\013\162\167\051\167\375\172\350\077\170\040\052\150\276\336\157 +\010\346\265\205\107\200\067\371\161\226\213\245\230\126\227\174 +\021\145\026\216\324\316\330\047\324\371\132\305\247\215\273\321 +\067\015\245\253\145\135\332\164\223\210\136\333\165\366\177\233 +\302\232\261\155\010\002\014\230\112\273\315\060\257\166\065\002 +\205\126\043\121\011\100\011\005\367\360\075\036\302\310\172\032 +\272\305\101\025\271\015\166\264\264\244\270\105\375\215\243\073 +\075\003\052\315\263\225\177\064\173\335\241\117\331\072\377\047 +\365\015\302\001\234\377\131\165\132\032\311\347\322\375\177\117 +\017\265\376\015\074\346\240\326\373\265\166\134\264\060\115\020 +\077\376\342\353\132\016\261\117\117\120\176\010\063\002\221\127 +\062\111\211\247\100\020\120\027\153\237\143\272\262\262\126\230 +\166\364\377\162\351\004\234\324\247\114\117\366\072\037\132\124 +\061\157\313\272\062\255\370\155\257\105\307\173\143\104\337\302 +\375\170\350\112\212\260\164\165\026\336\217\002\003\001\000\001 +\243\102\060\100\060\017\006\003\125\035\023\001\001\377\004\005 +\060\003\001\001\377\060\035\006\003\125\035\016\004\026\004\024 +\200\032\252\103\301\311\177\213\032\226\105\274\075\273\153\110 +\122\154\133\253\060\016\006\003\125\035\017\001\001\377\004\004 +\003\002\001\006\060\015\006\011\052\206\110\206\367\015\001\001 +\014\005\000\003\202\002\001\000\052\165\201\241\202\040\352\177 +\126\256\011\060\227\020\170\364\331\100\024\122\244\356\152\177 +\360\011\050\326\020\143\340\116\173\311\061\307\010\245\027\353 +\257\206\342\227\007\117\251\016\242\205\314\355\244\200\201\035 +\132\123\006\074\114\032\251\267\204\206\317\174\365\205\012\160 +\231\320\355\066\221\215\347\167\056\316\204\234\050\206\055\045 +\065\214\114\001\346\175\333\141\135\342\167\204\323\001\321\142 +\335\014\242\012\144\244\374\360\355\072\110\362\071\354\065\326 +\241\172\027\161\354\323\322\354\270\046\373\255\025\160\126\112 +\317\144\300\271\140\133\367\346\315\240\302\003\053\371\262\345 +\332\272\245\067\034\330\215\332\171\164\052\147\344\242\172\307 +\054\215\245\301\152\201\154\314\365\251\071\152\042\175\242\342 +\010\315\351\223\333\272\313\037\165\167\236\367\230\257\024\344 +\073\240\114\247\162\347\265\136\123\111\314\377\222\127\361\131 +\053\011\272\351\122\223\300\017\105\013\141\326\154\131\163\013 +\330\371\001\057\332\003\117\067\034\364\337\203\136\013\101\240 +\261\174\071\000\241\154\320\330\264\221\162\053\033\077\242\232 +\321\304\337\053\325\310\225\175\204\315\166\033\334\344\044\306 +\077\025\042\075\205\247\102\053\355\176\161\131\141\110\302\075 +\221\143\100\174\051\263\200\026\012\045\374\030\140\016\123\255 +\016\052\316\374\101\072\315\261\344\152\153\314\071\155\310\115 +\145\270\252\223\210\170\156\017\002\213\340\226\216\164\037\320 +\176\341\164\267\366\201\152\344\043\254\216\375\217\065\035\232 +\161\012\117\052\125\057\376\030\301\000\367\173\110\212\145\257 +\157\010\035\103\347\132\270\037\244\350\003\353\375\114\265\264 +\223\250\061\336\103\235\022\275\347\351\244\322\337\157\374\157 +\106\243\357\061\116\215\027\253\033\251\340\370\251\064\126\241 +\016\347\164\354\250\207\205\330\167\065\113\215\076\156\162\174 +\110\314\037\162\263\161\164\324\044\206\274\310\300\343\171\024 +\001\316\331\372\201\306\134\263\371\135\014\070\276\316\362\216 +\215\137\075\045\341\121\071\043\250\352\000\216\004\263\277\162 +\240\302\272\203\373\315\244\227\165\040\232\277\247\120\342\335 +\255\054\037\364\077\243\310\061 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "TrustAsia SMIME RSA Root CA" +# Issuer: CN=TrustAsia SMIME RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:5a:ee:71:df:de:0c:57:85:b5:bb:36:22:d7:b8:76:46:02:73:ca:ff +# Subject: CN=TrustAsia SMIME RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:42:01 2024 +# Not Valid After : Sun May 15 05:42:00 2044 +# Fingerprint (SHA-256): C7:79:6B:EB:62:C1:01:BB:14:3D:26:2A:7C:96:A0:C6:16:81:83:22:3E:F5:0D:69:96:32:D8:6E:03:B8:CC:9B +# Fingerprint (SHA1): 8C:69:21:7C:CE:49:73:36:5A:5C:EF:2B:B0:86:97:50:E3:E3:33:65 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia SMIME RSA Root CA" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\214\151\041\174\316\111\163\066\132\134\357\053\260\206\227\120 +\343\343\063\145 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\151\206\230\353\337\305\241\132\301\244\153\324\074\243\373\266 +END +CKA_ISSUER MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\044\060\042\006\003\125\004\003\023 +\033\124\162\165\163\164\101\163\151\141\040\123\115\111\115\105 +\040\122\123\101\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\132\356\161\337\336\014\127\205\265\273\066\042\327\270 +\166\106\002\163\312\377 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "TrustAsia TLS ECC Root CA" +# +# Issuer: CN=TrustAsia TLS ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:36:74:e1:4d:7c:65:13:c9:ac:83:55:25:a0:3e:52:7e:2f:50:68:c7 +# Subject: CN=TrustAsia TLS ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:41:56 2024 +# Not Valid After : Sun May 15 05:41:55 2044 +# Fingerprint (SHA-256): C0:07:6B:9E:F0:53:1F:B1:A6:56:D6:7C:4E:BE:97:CD:5D:BA:A4:1E:F4:45:98:AC:C2:48:98:78:C9:2D:87:11 +# Fingerprint (SHA1): B5:EC:39:F3:A1:66:37:AE:C3:05:94:57:E2:BE:11:BE:B7:A1:7F:36 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia TLS ECC Root CA" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023 +\031\124\162\165\163\164\101\163\151\141\040\124\114\123\040\105 +\103\103\040\122\157\157\164\040\103\101 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023 +\031\124\162\165\163\164\101\163\151\141\040\124\114\123\040\105 +\103\103\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\066\164\341\115\174\145\023\311\254\203\125\045\240\076 +\122\176\057\120\150\307 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\002\061\060\202\001\267\240\003\002\001\002\002\024\066 +\164\341\115\174\145\023\311\254\203\125\045\240\076\122\176\057 +\120\150\307\060\012\006\010\052\206\110\316\075\004\003\003\060 +\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061\045 +\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101\163 +\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163\054 +\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023\031 +\124\162\165\163\164\101\163\151\141\040\124\114\123\040\105\103 +\103\040\122\157\157\164\040\103\101\060\036\027\015\062\064\060 +\065\061\065\060\065\064\061\065\066\132\027\015\064\064\060\065 +\061\065\060\065\064\061\065\065\132\060\130\061\013\060\011\006 +\003\125\004\006\023\002\103\116\061\045\060\043\006\003\125\004 +\012\023\034\124\162\165\163\164\101\163\151\141\040\124\145\143 +\150\156\157\154\157\147\151\145\163\054\040\111\156\143\056\061 +\042\060\040\006\003\125\004\003\023\031\124\162\165\163\164\101 +\163\151\141\040\124\114\123\040\105\103\103\040\122\157\157\164 +\040\103\101\060\166\060\020\006\007\052\206\110\316\075\002\001 +\006\005\053\201\004\000\042\003\142\000\004\270\177\245\133\077 +\001\076\175\360\210\155\256\051\230\341\233\134\123\231\333\367 +\010\377\325\152\340\216\313\104\246\360\301\214\275\117\324\316 +\324\210\123\350\136\127\327\116\276\054\077\363\022\247\000\351 +\202\343\052\133\062\174\113\233\024\051\236\370\055\203\265\353 +\216\061\111\075\046\141\351\035\162\213\211\266\012\273\234\063 +\065\017\332\354\336\251\112\037\311\063\261\243\102\060\100\060 +\017\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377 +\060\035\006\003\125\035\016\004\026\004\024\054\205\123\273\261 +\103\315\062\352\236\243\207\376\242\230\250\246\223\351\020\060 +\016\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060 +\012\006\010\052\206\110\316\075\004\003\003\003\150\000\060\145 +\002\060\124\107\327\303\055\141\206\110\364\171\132\125\015\065 +\057\137\015\366\147\154\167\100\032\106\347\370\150\133\116\047 +\035\270\230\175\177\223\277\010\115\304\332\105\060\241\017\136 +\112\170\002\061\000\243\221\207\362\021\063\203\303\301\212\221 +\072\114\053\120\261\275\042\224\135\065\211\163\203\305\233\031 +\376\264\241\351\324\241\146\266\001\245\066\371\330\150\141\050 +\267\164\341\242\061 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "TrustAsia TLS ECC Root CA" +# Issuer: CN=TrustAsia TLS ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:36:74:e1:4d:7c:65:13:c9:ac:83:55:25:a0:3e:52:7e:2f:50:68:c7 +# Subject: CN=TrustAsia TLS ECC Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:41:56 2024 +# Not Valid After : Sun May 15 05:41:55 2044 +# Fingerprint (SHA-256): C0:07:6B:9E:F0:53:1F:B1:A6:56:D6:7C:4E:BE:97:CD:5D:BA:A4:1E:F4:45:98:AC:C2:48:98:78:C9:2D:87:11 +# Fingerprint (SHA1): B5:EC:39:F3:A1:66:37:AE:C3:05:94:57:E2:BE:11:BE:B7:A1:7F:36 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia TLS ECC Root CA" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\265\354\071\363\241\146\067\256\303\005\224\127\342\276\021\276 +\267\241\177\066 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\011\110\004\167\322\374\145\223\161\146\261\021\225\117\006\214 +END +CKA_ISSUER MULTILINE_OCTAL +\060\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023 +\031\124\162\165\163\164\101\163\151\141\040\124\114\123\040\105 +\103\103\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\066\164\341\115\174\145\023\311\254\203\125\045\240\076 +\122\176\057\120\150\307 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "TrustAsia TLS RSA Root CA" +# +# Issuer: CN=TrustAsia TLS RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:1c:18:d8:cf:e5:53:3f:22:35:46:53:54:24:3c:6c:47:d1:5c:4a:9c +# Subject: CN=TrustAsia TLS RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:41:57 2024 +# Not Valid After : Sun May 15 05:41:56 2044 +# Fingerprint (SHA-256): 06:C0:8D:7D:AF:D8:76:97:1E:B1:12:4F:E6:7F:84:7E:C0:C7:A1:58:D3:EA:53:CB:E9:40:E2:EA:97:91:F4:C3 +# Fingerprint (SHA1): A5:46:50:C5:62:EA:95:9A:1A:A7:04:6F:17:58:C7:29:53:3D:03:FA +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia TLS RSA Root CA" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023 +\031\124\162\165\163\164\101\163\151\141\040\124\114\123\040\122 +\123\101\040\122\157\157\164\040\103\101 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023 +\031\124\162\165\163\164\101\163\151\141\040\124\114\123\040\122 +\123\101\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\034\030\330\317\345\123\077\042\065\106\123\124\044\074 +\154\107\321\134\112\234 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\005\200\060\202\003\150\240\003\002\001\002\002\024\034 +\030\330\317\345\123\077\042\065\106\123\124\044\074\154\107\321 +\134\112\234\060\015\006\011\052\206\110\206\367\015\001\001\014 +\005\000\060\130\061\013\060\011\006\003\125\004\006\023\002\103 +\116\061\045\060\043\006\003\125\004\012\023\034\124\162\165\163 +\164\101\163\151\141\040\124\145\143\150\156\157\154\157\147\151 +\145\163\054\040\111\156\143\056\061\042\060\040\006\003\125\004 +\003\023\031\124\162\165\163\164\101\163\151\141\040\124\114\123 +\040\122\123\101\040\122\157\157\164\040\103\101\060\036\027\015 +\062\064\060\065\061\065\060\065\064\061\065\067\132\027\015\064 +\064\060\065\061\065\060\065\064\061\065\066\132\060\130\061\013 +\060\011\006\003\125\004\006\023\002\103\116\061\045\060\043\006 +\003\125\004\012\023\034\124\162\165\163\164\101\163\151\141\040 +\124\145\143\150\156\157\154\157\147\151\145\163\054\040\111\156 +\143\056\061\042\060\040\006\003\125\004\003\023\031\124\162\165 +\163\164\101\163\151\141\040\124\114\123\040\122\123\101\040\122 +\157\157\164\040\103\101\060\202\002\042\060\015\006\011\052\206 +\110\206\367\015\001\001\001\005\000\003\202\002\017\000\060\202 +\002\012\002\202\002\001\000\303\026\270\033\152\244\104\163\345 +\326\116\364\271\317\133\013\301\321\232\201\365\143\260\217\103 +\301\273\010\132\032\172\341\007\166\046\037\217\151\126\276\376 +\066\140\320\014\203\315\224\352\347\305\055\134\057\005\026\002 +\236\012\250\057\345\140\046\124\226\370\230\100\035\254\256\235 +\164\147\057\124\373\224\143\230\343\046\112\203\306\225\266\011 +\103\120\315\015\175\336\104\016\140\022\117\133\065\275\277\231 +\070\155\175\154\332\342\150\163\037\371\061\245\031\020\163\005 +\052\303\062\031\205\352\064\252\335\102\036\060\215\077\236\265 +\036\141\325\157\275\000\162\162\255\022\077\252\246\111\163\362 +\206\025\225\014\020\137\121\144\316\377\167\270\311\155\254\345 +\325\230\361\231\056\154\343\311\104\371\265\103\047\010\115\366 +\176\336\104\171\273\262\214\034\332\323\113\154\056\326\303\170 +\267\114\325\244\344\332\334\212\216\016\377\017\303\246\140\046 +\050\317\066\277\372\127\012\354\133\077\351\060\026\173\304\333 +\304\324\144\240\060\373\345\375\035\161\222\335\051\217\101\130 +\336\000\255\072\375\075\174\032\250\261\027\360\116\064\170\130 +\045\326\205\041\353\171\035\320\334\253\317\142\074\260\307\227 +\213\326\320\237\323\376\074\336\305\343\374\072\203\160\204\041 +\035\011\302\241\374\273\050\041\145\123\140\172\220\155\226\070 +\133\377\361\327\172\133\155\323\311\160\111\112\272\035\072\320 +\120\332\062\040\031\344\213\077\353\325\026\046\067\074\373\165 +\236\260\007\160\270\024\140\167\334\366\017\134\122\012\274\135 +\155\215\121\012\332\305\030\310\233\155\334\260\203\263\177\243 +\116\170\114\230\045\253\362\176\056\040\136\202\025\246\326\330 +\217\254\345\315\062\206\310\371\344\332\211\342\073\076\223\305 +\023\152\377\307\367\030\374\147\265\357\030\054\124\253\100\323 +\154\115\355\305\310\267\070\117\144\304\224\114\117\240\315\256 +\245\306\047\045\165\047\155\306\332\234\216\260\005\231\325\050 +\021\305\041\324\270\374\307\226\253\112\144\131\141\153\023\374 +\113\314\222\246\017\244\121\277\016\130\220\331\202\203\071\246 +\137\263\372\156\222\263\315\063\016\205\250\361\051\323\253\131 +\255\326\333\336\324\053\201\002\003\001\000\001\243\102\060\100 +\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001\001 +\377\060\035\006\003\125\035\016\004\026\004\024\270\007\221\171 +\134\006\364\106\375\173\131\312\132\046\221\247\105\053\370\123 +\060\016\006\003\125\035\017\001\001\377\004\004\003\002\001\006 +\060\015\006\011\052\206\110\206\367\015\001\001\014\005\000\003 +\202\002\001\000\041\233\152\005\040\135\030\026\247\022\244\367 +\107\077\315\312\073\256\216\300\202\316\334\110\045\170\027\154 +\340\340\160\304\326\226\331\331\366\277\172\234\023\273\123\225 +\222\377\317\222\340\363\305\047\065\127\250\073\242\031\353\370 +\212\243\004\336\151\213\344\074\074\275\345\257\320\022\033\345 +\211\153\163\233\157\045\002\113\220\202\257\100\302\255\272\232 +\140\044\132\201\115\005\030\243\342\063\171\172\013\037\223\355 +\354\071\112\365\023\004\354\215\164\235\201\012\250\157\350\166 +\376\213\117\053\151\022\206\012\064\066\335\202\233\157\117\340 +\163\335\111\177\050\076\311\073\243\127\004\330\223\331\074\051 +\333\022\020\150\341\304\211\270\006\040\347\033\172\274\261\223 +\141\232\031\100\021\265\152\205\127\001\361\266\132\055\046\163 +\047\226\371\271\077\133\320\210\235\344\240\375\272\116\225\011 +\203\177\167\334\121\005\224\235\040\161\166\261\354\372\211\265 +\234\056\205\361\271\133\044\132\261\011\253\332\312\032\007\315 +\206\337\333\151\333\264\110\030\000\055\274\242\304\211\105\043 +\245\016\341\104\145\076\212\301\152\060\035\342\140\370\072\252 +\207\011\102\271\201\222\334\045\210\230\211\361\174\065\361\142 +\312\356\171\370\031\057\376\137\370\333\207\316\352\250\017\014 +\246\350\013\240\074\340\153\224\230\234\177\255\006\346\034\352 +\102\020\137\342\046\025\074\067\071\367\327\274\356\270\345\357 +\003\356\275\042\373\050\206\064\130\304\132\177\141\242\170\017 +\136\363\312\235\274\033\074\247\310\055\366\247\042\021\312\003 +\330\347\147\012\212\016\313\065\216\064\071\330\310\352\215\237 +\144\340\067\260\154\327\305\217\301\220\141\046\333\044\214\036 +\112\300\210\337\065\220\316\077\002\364\144\141\336\307\310\007 +\225\336\062\030\072\217\242\102\100\044\345\326\063\135\174\256 +\357\261\115\117\324\127\220\065\152\334\256\004\227\111\211\064 +\227\056\060\004\347\230\367\333\013\001\220\301\037\012\077\370 +\302\376\116\372\333\232\163\163\026\274\005\270\171\330\131\257 +\006\347\077\147\070\071\261\174\253\224\340\051\024\246\050\362 +\337\155\342\232\333\124\103\370\107\130\243\135\164\025\234\301 +\253\260\307\064 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "TrustAsia TLS RSA Root CA" +# Issuer: CN=TrustAsia TLS RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Serial Number:1c:18:d8:cf:e5:53:3f:22:35:46:53:54:24:3c:6c:47:d1:5c:4a:9c +# Subject: CN=TrustAsia TLS RSA Root CA,O="TrustAsia Technologies, Inc.",C=CN +# Not Valid Before: Wed May 15 05:41:57 2024 +# Not Valid After : Sun May 15 05:41:56 2044 +# Fingerprint (SHA-256): 06:C0:8D:7D:AF:D8:76:97:1E:B1:12:4F:E6:7F:84:7E:C0:C7:A1:58:D3:EA:53:CB:E9:40:E2:EA:97:91:F4:C3 +# Fingerprint (SHA1): A5:46:50:C5:62:EA:95:9A:1A:A7:04:6F:17:58:C7:29:53:3D:03:FA +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "TrustAsia TLS RSA Root CA" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\245\106\120\305\142\352\225\232\032\247\004\157\027\130\307\051 +\123\075\003\372 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\073\236\303\206\017\064\074\153\305\106\304\216\035\347\031\022 +END +CKA_ISSUER MULTILINE_OCTAL +\060\130\061\013\060\011\006\003\125\004\006\023\002\103\116\061 +\045\060\043\006\003\125\004\012\023\034\124\162\165\163\164\101 +\163\151\141\040\124\145\143\150\156\157\154\157\147\151\145\163 +\054\040\111\156\143\056\061\042\060\040\006\003\125\004\003\023 +\031\124\162\165\163\164\101\163\151\141\040\124\114\123\040\122 +\123\101\040\122\157\157\164\040\103\101 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\034\030\330\317\345\123\077\042\065\106\123\124\044\074 +\154\107\321\134\112\234 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + # # Certificate "D-TRUST EV Root CA 2 2023" # @@ -26138,3 +26578,343 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "SwissSign RSA SMIME Root CA 2022 - 1" +# +# Issuer: CN=SwissSign RSA SMIME Root CA 2022 - 1,O=SwissSign AG,C=CH +# Serial Number:46:0e:d4:01:71:90:a0:1a:83:2c:4a:42:10:28:15:d2:61:1b:ad:32 +# Subject: CN=SwissSign RSA SMIME Root CA 2022 - 1,O=SwissSign AG,C=CH +# Not Valid Before: Wed Jun 08 10:53:13 2022 +# Not Valid After : Sat Jun 08 10:53:13 2047 +# Fingerprint (SHA-256): 9A:12:C3:92:BF:E5:78:91:A0:C5:45:30:9D:4D:9F:D5:67:E4:80:CB:61:3D:63:42:27:8B:19:5C:79:A7:93:1F +# Fingerprint (SHA1): 14:D7:65:62:74:10:50:47:9F:8B:32:C6:86:8A:18:FA:E1:19:99:B0 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "SwissSign RSA SMIME Root CA 2022 - 1" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\123\061\013\060\011\006\003\125\004\006\023\002\103\110\061 +\025\060\023\006\003\125\004\012\023\014\123\167\151\163\163\123 +\151\147\156\040\101\107\061\055\060\053\006\003\125\004\003\023 +\044\123\167\151\163\163\123\151\147\156\040\122\123\101\040\123 +\115\111\115\105\040\122\157\157\164\040\103\101\040\062\060\062 +\062\040\055\040\061 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\123\061\013\060\011\006\003\125\004\006\023\002\103\110\061 +\025\060\023\006\003\125\004\012\023\014\123\167\151\163\163\123 +\151\147\156\040\101\107\061\055\060\053\006\003\125\004\003\023 +\044\123\167\151\163\163\123\151\147\156\040\122\123\101\040\123 +\115\111\115\105\040\122\157\157\164\040\103\101\040\062\060\062 +\062\040\055\040\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\106\016\324\001\161\220\240\032\203\054\112\102\020\050 +\025\322\141\033\255\062 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\005\227\060\202\003\177\240\003\002\001\002\002\024\106 +\016\324\001\161\220\240\032\203\054\112\102\020\050\025\322\141 +\033\255\062\060\015\006\011\052\206\110\206\367\015\001\001\013 +\005\000\060\123\061\013\060\011\006\003\125\004\006\023\002\103 +\110\061\025\060\023\006\003\125\004\012\023\014\123\167\151\163 +\163\123\151\147\156\040\101\107\061\055\060\053\006\003\125\004 +\003\023\044\123\167\151\163\163\123\151\147\156\040\122\123\101 +\040\123\115\111\115\105\040\122\157\157\164\040\103\101\040\062 +\060\062\062\040\055\040\061\060\036\027\015\062\062\060\066\060 +\070\061\060\065\063\061\063\132\027\015\064\067\060\066\060\070 +\061\060\065\063\061\063\132\060\123\061\013\060\011\006\003\125 +\004\006\023\002\103\110\061\025\060\023\006\003\125\004\012\023 +\014\123\167\151\163\163\123\151\147\156\040\101\107\061\055\060 +\053\006\003\125\004\003\023\044\123\167\151\163\163\123\151\147 +\156\040\122\123\101\040\123\115\111\115\105\040\122\157\157\164 +\040\103\101\040\062\060\062\062\040\055\040\061\060\202\002\042 +\060\015\006\011\052\206\110\206\367\015\001\001\001\005\000\003 +\202\002\017\000\060\202\002\012\002\202\002\001\000\324\373\372 +\077\206\242\231\160\011\072\311\326\241\116\001\316\106\265\055 +\044\110\015\105\351\254\311\032\327\062\200\244\346\323\312\326 +\362\051\067\354\232\054\326\201\316\346\033\235\261\017\101\337 +\130\323\137\252\240\171\131\013\214\255\371\305\371\034\373\303 +\351\065\100\164\303\301\014\313\147\373\234\136\014\043\371\320 +\057\372\114\202\105\034\265\365\037\370\031\156\332\223\267\116 +\150\203\176\142\055\035\214\225\037\160\331\316\132\214\041\135 +\250\276\010\251\126\155\331\367\271\220\231\307\073\327\275\236 +\056\311\147\127\056\041\316\360\062\203\373\004\001\371\267\202 +\104\015\262\313\172\011\241\110\076\117\300\013\152\033\033\354 +\317\035\236\177\006\220\254\050\005\013\250\346\124\073\242\247 +\054\071\023\231\250\373\064\353\365\360\275\001\330\210\021\310 +\256\272\031\002\111\002\334\212\054\264\275\141\140\354\235\170 +\134\152\213\057\027\206\136\362\117\223\000\153\135\305\262\251 +\245\030\352\346\155\176\127\005\373\007\374\274\174\241\103\261 +\146\034\250\147\373\253\067\366\252\252\270\172\101\367\071\325 +\214\237\256\162\066\047\344\142\306\103\231\361\241\101\351\377 +\211\237\017\111\257\311\024\006\027\047\144\071\015\245\264\052 +\133\354\074\373\237\305\137\306\073\135\046\031\362\204\051\270 +\225\104\011\122\375\154\060\320\142\217\050\245\201\226\053\224 +\057\046\165\344\011\214\012\337\070\363\176\135\070\216\202\232 +\214\334\236\256\316\022\102\072\042\362\065\215\117\322\032\310 +\111\063\013\372\066\077\377\054\153\152\040\161\114\315\255\020 +\077\151\062\204\216\134\356\123\210\104\342\335\314\003\060\222 +\206\171\220\052\113\165\373\122\142\304\364\157\115\367\333\043 +\241\030\335\105\123\027\232\143\044\110\211\042\315\176\233\001 +\034\200\050\003\217\133\053\372\037\343\174\031\275\346\217\261 +\100\166\240\362\307\067\262\062\224\020\062\315\247\023\227\361 +\073\054\172\064\042\173\164\072\100\342\257\202\370\301\301\170 +\374\137\344\065\177\300\364\114\360\114\262\352\207\003\162\045 +\131\203\052\010\244\121\336\317\356\250\347\350\100\077\210\360 +\066\253\011\116\330\240\250\177\363\341\011\333\271\002\003\001 +\000\001\243\143\060\141\060\017\006\003\125\035\023\001\001\377 +\004\005\060\003\001\001\377\060\016\006\003\125\035\017\001\001 +\377\004\004\003\002\001\006\060\037\006\003\125\035\043\004\030 +\060\026\200\024\314\056\255\211\214\203\343\100\243\045\151\245 +\352\222\175\322\067\072\307\306\060\035\006\003\125\035\016\004 +\026\004\024\314\056\255\211\214\203\343\100\243\045\151\245\352 +\222\175\322\067\072\307\306\060\015\006\011\052\206\110\206\367 +\015\001\001\013\005\000\003\202\002\001\000\000\007\146\026\245 +\355\307\271\277\274\310\221\255\130\355\136\022\005\263\366\106 +\233\173\344\204\020\057\007\261\132\136\062\156\155\000\360\136 +\307\232\142\071\207\115\344\074\363\276\366\272\152\123\154\204 +\155\007\324\141\312\147\146\276\233\076\105\060\235\121\322\327 +\132\102\256\235\222\016\043\253\320\025\224\076\250\232\312\233 +\355\301\302\137\041\243\231\200\374\271\246\141\016\120\200\200 +\047\307\350\175\240\324\224\172\230\003\347\356\102\213\363\122 +\120\134\357\276\260\166\132\034\011\241\277\203\300\036\166\145 +\320\045\101\133\151\221\223\167\371\214\113\360\054\333\233\006 +\000\027\203\372\132\224\264\206\211\357\274\012\013\022\370\006 +\115\322\163\342\221\070\135\271\152\113\117\247\257\332\046\045 +\222\043\032\174\037\047\015\221\204\357\027\162\366\106\353\153 +\073\067\251\324\325\232\143\272\136\171\214\052\265\233\242\064 +\265\314\226\047\371\171\010\074\177\155\340\377\174\334\305\046 +\257\303\241\172\151\026\335\207\065\163\306\153\061\153\126\001 +\055\117\231\331\356\312\341\320\203\336\266\205\347\026\370\321 +\256\063\110\373\032\317\135\137\212\204\141\164\007\157\031\260 +\121\041\262\241\004\261\173\123\217\357\242\105\255\037\230\335 +\371\152\004\154\252\066\305\257\214\352\051\111\112\347\377\127 +\263\306\074\021\111\030\027\346\146\205\341\350\043\362\213\016 +\074\223\304\077\166\116\176\142\242\051\313\026\060\336\054\151 +\257\221\247\342\127\345\063\114\277\330\216\007\242\177\241\065 +\106\151\112\250\040\051\377\353\336\040\225\131\261\256\115\060 +\153\330\232\264\003\037\302\070\344\040\325\016\326\032\060\114 +\150\234\214\340\355\241\017\216\102\135\353\200\052\022\171\246 +\027\027\264\225\052\216\064\221\247\275\321\254\250\032\103\041 +\213\336\357\340\254\106\045\145\012\306\053\241\233\076\042\350 +\030\070\265\046\366\054\312\010\040\336\060\321\255\124\375\334 +\110\025\237\315\247\101\327\067\070\205\060\117\022\210\103\064 +\203\327\052\115\324\000\127\134\345\312\360\335\341\222\050\053 +\030\165\275\107\244\102\023\351\126\132\215\112\136\316\016\165 +\065\200\163\031\017\054\051\213\273\225\270 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "SwissSign RSA SMIME Root CA 2022 - 1" +# Issuer: CN=SwissSign RSA SMIME Root CA 2022 - 1,O=SwissSign AG,C=CH +# Serial Number:46:0e:d4:01:71:90:a0:1a:83:2c:4a:42:10:28:15:d2:61:1b:ad:32 +# Subject: CN=SwissSign RSA SMIME Root CA 2022 - 1,O=SwissSign AG,C=CH +# Not Valid Before: Wed Jun 08 10:53:13 2022 +# Not Valid After : Sat Jun 08 10:53:13 2047 +# Fingerprint (SHA-256): 9A:12:C3:92:BF:E5:78:91:A0:C5:45:30:9D:4D:9F:D5:67:E4:80:CB:61:3D:63:42:27:8B:19:5C:79:A7:93:1F +# Fingerprint (SHA1): 14:D7:65:62:74:10:50:47:9F:8B:32:C6:86:8A:18:FA:E1:19:99:B0 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "SwissSign RSA SMIME Root CA 2022 - 1" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\024\327\145\142\164\020\120\107\237\213\062\306\206\212\030\372 +\341\031\231\260 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\232\063\065\330\302\042\023\366\370\153\226\000\022\032\110\141 +END +CKA_ISSUER MULTILINE_OCTAL +\060\123\061\013\060\011\006\003\125\004\006\023\002\103\110\061 +\025\060\023\006\003\125\004\012\023\014\123\167\151\163\163\123 +\151\147\156\040\101\107\061\055\060\053\006\003\125\004\003\023 +\044\123\167\151\163\163\123\151\147\156\040\122\123\101\040\123 +\115\111\115\105\040\122\157\157\164\040\103\101\040\062\060\062 +\062\040\055\040\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\106\016\324\001\161\220\240\032\203\054\112\102\020\050 +\025\322\141\033\255\062 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "SwissSign RSA TLS Root CA 2022 - 1" +# +# Issuer: CN=SwissSign RSA TLS Root CA 2022 - 1,O=SwissSign AG,C=CH +# Serial Number:43:fa:0c:5f:4e:1b:80:18:44:ef:d1:b4:4f:35:1f:44:f4:80:ed:cb +# Subject: CN=SwissSign RSA TLS Root CA 2022 - 1,O=SwissSign AG,C=CH +# Not Valid Before: Wed Jun 08 11:08:22 2022 +# Not Valid After : Sat Jun 08 11:08:22 2047 +# Fingerprint (SHA-256): 19:31:44:F4:31:E0:FD:DB:74:07:17:D4:DE:92:6A:57:11:33:88:4B:43:60:D3:0E:27:29:13:CB:E6:60:CE:41 +# Fingerprint (SHA1): 81:34:0A:BE:4C:CD:CE:CC:E7:7D:CC:8A:D4:57:E2:45:A0:77:5D:CE +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "SwissSign RSA TLS Root CA 2022 - 1" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\121\061\013\060\011\006\003\125\004\006\023\002\103\110\061 +\025\060\023\006\003\125\004\012\023\014\123\167\151\163\163\123 +\151\147\156\040\101\107\061\053\060\051\006\003\125\004\003\023 +\042\123\167\151\163\163\123\151\147\156\040\122\123\101\040\124 +\114\123\040\122\157\157\164\040\103\101\040\062\060\062\062\040 +\055\040\061 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\121\061\013\060\011\006\003\125\004\006\023\002\103\110\061 +\025\060\023\006\003\125\004\012\023\014\123\167\151\163\163\123 +\151\147\156\040\101\107\061\053\060\051\006\003\125\004\003\023 +\042\123\167\151\163\163\123\151\147\156\040\122\123\101\040\124 +\114\123\040\122\157\157\164\040\103\101\040\062\060\062\062\040 +\055\040\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\103\372\014\137\116\033\200\030\104\357\321\264\117\065 +\037\104\364\200\355\313 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\005\223\060\202\003\173\240\003\002\001\002\002\024\103 +\372\014\137\116\033\200\030\104\357\321\264\117\065\037\104\364 +\200\355\313\060\015\006\011\052\206\110\206\367\015\001\001\013 +\005\000\060\121\061\013\060\011\006\003\125\004\006\023\002\103 +\110\061\025\060\023\006\003\125\004\012\023\014\123\167\151\163 +\163\123\151\147\156\040\101\107\061\053\060\051\006\003\125\004 +\003\023\042\123\167\151\163\163\123\151\147\156\040\122\123\101 +\040\124\114\123\040\122\157\157\164\040\103\101\040\062\060\062 +\062\040\055\040\061\060\036\027\015\062\062\060\066\060\070\061 +\061\060\070\062\062\132\027\015\064\067\060\066\060\070\061\061 +\060\070\062\062\132\060\121\061\013\060\011\006\003\125\004\006 +\023\002\103\110\061\025\060\023\006\003\125\004\012\023\014\123 +\167\151\163\163\123\151\147\156\040\101\107\061\053\060\051\006 +\003\125\004\003\023\042\123\167\151\163\163\123\151\147\156\040 +\122\123\101\040\124\114\123\040\122\157\157\164\040\103\101\040 +\062\060\062\062\040\055\040\061\060\202\002\042\060\015\006\011 +\052\206\110\206\367\015\001\001\001\005\000\003\202\002\017\000 +\060\202\002\012\002\202\002\001\000\313\052\150\342\013\303\127 +\274\065\143\274\160\245\073\363\214\074\116\127\226\156\303\116 +\066\244\366\002\312\036\252\256\270\336\250\257\035\166\332\272 +\065\320\221\160\007\337\263\006\362\212\362\056\125\121\173\273 +\054\044\313\177\222\046\200\243\264\224\366\202\241\244\350\372 +\165\035\131\363\007\152\141\144\342\306\214\225\257\243\273\216 +\157\126\317\161\314\136\201\141\015\155\362\253\002\056\244\227 +\345\161\374\212\260\221\040\133\234\164\122\155\256\025\047\131 +\170\362\011\312\145\016\177\313\364\353\347\334\251\114\167\366 +\053\026\004\225\256\234\161\245\077\052\332\101\102\347\074\204 +\020\364\341\075\214\153\342\053\221\107\125\117\270\126\276\105 +\336\042\121\115\116\050\331\137\031\101\006\217\016\115\006\340 +\160\100\043\001\152\344\313\023\233\163\254\115\024\110\222\055 +\376\155\247\370\207\153\171\165\341\276\020\261\252\210\100\131 +\124\327\317\304\320\233\104\263\070\151\144\214\201\321\043\176 +\252\071\074\073\017\237\112\173\202\312\153\157\312\042\076\061 +\320\260\320\052\034\222\212\217\330\031\234\107\344\076\014\271 +\302\315\276\101\014\370\244\107\005\333\301\027\060\070\072\151 +\334\315\303\151\043\375\232\017\002\316\020\152\316\312\370\271 +\051\243\066\211\206\256\013\300\117\143\271\006\131\111\136\016 +\301\151\263\012\363\167\176\056\235\214\263\047\230\322\231\215 +\045\247\037\206\263\246\124\160\070\374\175\135\350\117\203\014 +\321\223\345\022\344\124\332\076\362\255\072\336\076\074\105\360 +\050\017\006\271\341\333\227\173\231\105\236\335\376\225\131\004 +\057\165\077\323\256\211\231\206\254\024\264\250\204\372\310\135 +\073\033\130\223\301\027\224\125\310\013\343\202\171\204\237\363 +\000\204\064\356\334\061\325\217\362\372\117\226\114\006\252\170 +\373\336\144\242\043\315\037\076\305\214\274\067\124\016\273\132 +\162\125\357\310\133\265\162\370\170\337\067\040\114\127\221\163 +\222\163\254\030\167\103\202\040\151\354\351\254\051\106\345\013 +\116\370\067\163\211\226\212\034\155\275\357\276\330\266\364\312 +\300\375\107\360\256\013\130\040\305\310\035\066\256\227\215\120 +\203\046\044\051\367\235\073\017\005\002\003\001\000\001\243\143 +\060\141\060\017\006\003\125\035\023\001\001\377\004\005\060\003 +\001\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003 +\002\001\006\060\037\006\003\125\035\043\004\030\060\026\200\024 +\157\216\142\213\223\103\260\341\100\366\247\303\375\361\017\270 +\017\025\070\245\060\035\006\003\125\035\016\004\026\004\024\157 +\216\142\213\223\103\260\341\100\366\247\303\375\361\017\270\017 +\025\070\245\060\015\006\011\052\206\110\206\367\015\001\001\013 +\005\000\003\202\002\001\000\254\054\051\101\175\372\134\365\032 +\225\030\277\054\251\212\251\044\124\165\365\270\100\253\313\250 +\044\121\053\030\077\143\251\256\230\126\053\005\103\042\243\267 +\327\106\236\300\052\022\075\216\226\226\100\337\014\063\213\153 +\067\221\072\225\273\071\051\155\300\002\154\212\224\013\007\002 +\115\030\076\373\373\173\365\166\075\233\366\136\060\006\130\063 +\036\252\170\325\346\124\004\072\262\202\011\215\316\026\063\131 +\105\050\361\245\243\227\016\103\043\375\013\040\200\220\377\343 +\046\317\270\144\221\345\005\217\023\240\166\015\327\067\014\020 +\210\226\364\076\276\225\275\361\303\175\360\243\303\171\107\013 +\134\222\025\143\355\122\165\212\347\106\151\313\121\125\013\052 +\114\365\362\144\117\251\134\377\147\062\216\125\055\062\202\034 +\200\057\152\221\370\313\274\176\030\242\046\250\056\243\123\050 +\207\355\127\345\145\172\116\000\112\133\116\123\311\142\066\275 +\302\216\133\353\314\156\047\201\030\131\213\104\143\237\325\014 +\145\364\051\145\177\221\054\345\177\176\350\211\317\217\040\313 +\155\007\102\021\121\046\062\212\056\072\107\023\270\215\275\107 +\015\011\360\026\244\355\226\206\056\031\330\276\214\072\350\105 +\056\021\272\256\132\347\271\277\261\314\217\340\240\377\270\263 +\321\205\173\171\146\243\071\265\073\146\330\100\276\317\267\147 +\213\110\311\031\045\125\374\275\215\317\136\332\116\246\362\151 +\316\375\177\114\167\320\301\106\065\230\134\043\233\002\105\103 +\224\132\335\274\107\255\042\376\272\136\057\221\051\051\206\173 +\041\336\156\144\267\313\015\217\067\133\243\010\152\353\364\335 +\002\217\120\003\002\261\270\067\150\226\120\353\270\137\324\050 +\212\245\042\014\212\204\360\131\056\325\067\321\141\345\102\163 +\130\052\201\367\166\333\342\342\115\015\137\366\267\276\005\264 +\256\116\015\336\026\075\003\201\263\046\136\113\270\113\000\317 +\377\214\027\272\154\140\055\047\207\067\044\346\172\140\057\265 +\323\203\004\252\117\103\165\242\301\203\262\047\230\053\261\016 +\200\272\300\205\136\102\271\337\261\140\221\323\353\030\176\160 +\170\256\166\203\276\161\132\320\220\343\312\301\026\045\147\112 +\360\266\173\272\341\234\331 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "SwissSign RSA TLS Root CA 2022 - 1" +# Issuer: CN=SwissSign RSA TLS Root CA 2022 - 1,O=SwissSign AG,C=CH +# Serial Number:43:fa:0c:5f:4e:1b:80:18:44:ef:d1:b4:4f:35:1f:44:f4:80:ed:cb +# Subject: CN=SwissSign RSA TLS Root CA 2022 - 1,O=SwissSign AG,C=CH +# Not Valid Before: Wed Jun 08 11:08:22 2022 +# Not Valid After : Sat Jun 08 11:08:22 2047 +# Fingerprint (SHA-256): 19:31:44:F4:31:E0:FD:DB:74:07:17:D4:DE:92:6A:57:11:33:88:4B:43:60:D3:0E:27:29:13:CB:E6:60:CE:41 +# Fingerprint (SHA1): 81:34:0A:BE:4C:CD:CE:CC:E7:7D:CC:8A:D4:57:E2:45:A0:77:5D:CE +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "SwissSign RSA TLS Root CA 2022 - 1" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\201\064\012\276\114\315\316\314\347\175\314\212\324\127\342\105 +\240\167\135\316 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\026\056\344\031\166\201\205\272\216\221\130\361\025\357\162\071 +END +CKA_ISSUER MULTILINE_OCTAL +\060\121\061\013\060\011\006\003\125\004\006\023\002\103\110\061 +\025\060\023\006\003\125\004\012\023\014\123\167\151\163\163\123 +\151\147\156\040\101\107\061\053\060\051\006\003\125\004\003\023 +\042\123\167\151\163\163\123\151\147\156\040\122\123\101\040\124 +\114\123\040\122\157\157\164\040\103\101\040\062\060\062\062\040 +\055\040\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\103\372\014\137\116\033\200\030\104\357\321\264\117\065 +\037\104\364\200\355\313 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE diff --git a/packages/bun-usockets/src/context.c b/packages/bun-usockets/src/context.c index 048f773858..605bb6de11 100644 --- a/packages/bun-usockets/src/context.c +++ b/packages/bun-usockets/src/context.c @@ -130,6 +130,7 @@ void us_internal_socket_context_unlink_socket(int ssl, struct us_socket_context_ next->prev = prev; } } + us_internal_disable_sweep_timer(context->loop); us_socket_context_unref(ssl, context); } void us_internal_socket_context_unlink_connecting_socket(int ssl, struct us_socket_context_t *context, struct us_connecting_socket_t *c) { @@ -147,6 +148,7 @@ void us_internal_socket_context_unlink_connecting_socket(int ssl, struct us_sock next->prev_pending = prev; } } + us_internal_disable_sweep_timer(context->loop); us_socket_context_unref(ssl, context); } @@ -172,6 +174,7 @@ void us_internal_socket_context_link_connecting_socket(int ssl, struct us_socket } context->head_connecting_sockets = c; us_socket_context_ref(ssl, context); + us_internal_enable_sweep_timer(context->loop); } @@ -185,6 +188,7 @@ void us_internal_socket_context_link_socket(struct us_socket_context_t *context, } context->head_sockets = s; us_socket_context_ref(0, context); + us_internal_enable_sweep_timer(context->loop); } struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context) { diff --git a/packages/bun-usockets/src/crypto/default_ciphers.h b/packages/bun-usockets/src/crypto/default_ciphers.h new file mode 100644 index 0000000000..791aad777f --- /dev/null +++ b/packages/bun-usockets/src/crypto/default_ciphers.h @@ -0,0 +1,58 @@ +// TLSv1.3 suites start with TLS_, and are the OpenSSL defaults, see: +// https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_ciphersuites.html +#ifndef DEFAULT_CIPHER_LIST +#define DEFAULT_CIPHER_LIST \ + "ECDHE-RSA-AES128-GCM-SHA256:" \ + "ECDHE-ECDSA-AES128-GCM-SHA256:" \ + "ECDHE-RSA-AES256-GCM-SHA384:" \ + "ECDHE-ECDSA-AES256-GCM-SHA384:" \ + "ECDHE-RSA-AES128-SHA256:" \ + "ECDHE-RSA-AES256-SHA384:" \ + "HIGH:" \ + "!aNULL:" \ + "!eNULL:" \ + "!EXPORT:" \ + "!DES:" \ + "!RC4:" \ + "!MD5:" \ + "!PSK:" \ + "!SRP:" \ + "!CAMELLIA" +#endif + +// BoringSSL does not support legacy DHE ciphers and dont support SSL_CTX_set_cipher_list (see https://github.com/envoyproxy/envoy/issues/8848#issuecomment-548672667) +// Node.js full list bellow + +// In node.js they filter TLS_* ciphers and use SSL_CTX_set_cipher_list (TODO: Electron has a patch https://github.com/nodejs/node/issues/25890) +// if passed to SSL_CTX_set_cipher_list it will be filtered out and not used in BoringSSL +// "TLS_AES_256_GCM_SHA384:" \ +// "TLS_CHACHA20_POLY1305_SHA256:" \ +// "TLS_AES_128_GCM_SHA256:" \ + +// Supported by BoringSSL: +// "ECDHE-RSA-AES128-GCM-SHA256:" \ +// "ECDHE-ECDSA-AES128-GCM-SHA256:" \ +// "ECDHE-RSA-AES256-GCM-SHA384:" \ +// "ECDHE-ECDSA-AES256-GCM-SHA384:" \ +// "ECDHE-RSA-AES128-SHA256:" \ +// "ECDHE-RSA-AES256-SHA384:" \ + +// Not supported by BoringSSL: +// "ECDHE-RSA-AES256-SHA256:" \ +// "DHE-RSA-AES128-GCM-SHA256:" \ +// "DHE-RSA-AES128-SHA256:" \ +// "DHE-RSA-AES256-SHA384:" \ +// "DHE-RSA-AES256-SHA256:" \ + + +// Also present in Node.js and supported by BoringSSL: +// "HIGH:" \ +// "!aNULL:" \ +// "!eNULL:" \ +// "!EXPORT:" \ +// "!DES:" \ +// "!RC4:" \ +// "!MD5:" \ +// "!PSK:" \ +// "!SRP:" \ +// "!CAMELLIA" \ No newline at end of file diff --git a/packages/bun-usockets/src/crypto/openssl.c b/packages/bun-usockets/src/crypto/openssl.c index 7e8c712555..dbc4693ee9 100644 --- a/packages/bun-usockets/src/crypto/openssl.c +++ b/packages/bun-usockets/src/crypto/openssl.c @@ -45,7 +45,7 @@ void *sni_find(void *sni, const char *hostname); #endif #include "./root_certs_header.h" - +#include "./default_ciphers.h" struct loop_ssl_data { char *ssl_read_input, *ssl_read_output; unsigned int ssl_read_input_length; @@ -848,21 +848,24 @@ create_ssl_context_from_options(struct us_socket_context_options_t options) { return NULL; } - /* OWASP Cipher String 'A+' - * (https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) */ - if (SSL_CTX_set_cipher_list( - ssl_context, - "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-" - "AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256") != 1) { + if (!SSL_CTX_set_cipher_list(ssl_context, DEFAULT_CIPHER_LIST)) { free_ssl_context(ssl_context); return NULL; } } if (options.ssl_ciphers) { - if (SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers) != 1) { - free_ssl_context(ssl_context); - return NULL; + if (!SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers)) { + unsigned long ssl_err = ERR_get_error(); + if (!(strlen(options.ssl_ciphers) == 0 && ERR_GET_REASON(ssl_err) == SSL_R_NO_CIPHER_MATCH)) { + // TLS1.2 ciphers were deliberately cleared, so don't consider + // SSL_R_NO_CIPHER_MATCH to be an error (this is how _set_cipher_suites() + // works). If the user actually sets a value (like "no-such-cipher"), then + // that's actually an error. + free_ssl_context(ssl_context); + return NULL; + } + ERR_clear_error(); } } @@ -1288,21 +1291,27 @@ SSL_CTX *create_ssl_context_from_bun_options( return NULL; } - /* OWASP Cipher String 'A+' - * (https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) */ - if (SSL_CTX_set_cipher_list( - ssl_context, - "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-" - "AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256") != 1) { + if (!SSL_CTX_set_cipher_list(ssl_context, DEFAULT_CIPHER_LIST)) { free_ssl_context(ssl_context); return NULL; } } if (options.ssl_ciphers) { - if (SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers) != 1) { - free_ssl_context(ssl_context); - return NULL; + if (!SSL_CTX_set_cipher_list(ssl_context, options.ssl_ciphers)) { + unsigned long ssl_err = ERR_get_error(); + if (!(strlen(options.ssl_ciphers) == 0 && ERR_GET_REASON(ssl_err) == SSL_R_NO_CIPHER_MATCH)) { + char error_msg[256]; + ERR_error_string_n(ERR_peek_last_error(), error_msg, sizeof(error_msg)); + // TLS1.2 ciphers were deliberately cleared, so don't consider + // SSL_R_NO_CIPHER_MATCH to be an error (this is how _set_cipher_suites() + // works). If the user actually sets a value (like "no-such-cipher"), then + // that's actually an error. + *err = CREATE_BUN_SOCKET_ERROR_INVALID_CIPHERS; + free_ssl_context(ssl_context); + return NULL; + } + ERR_clear_error(); } } diff --git a/packages/bun-usockets/src/crypto/root_certs.cpp b/packages/bun-usockets/src/crypto/root_certs.cpp index 877685a8c8..ba935a5a0c 100644 --- a/packages/bun-usockets/src/crypto/root_certs.cpp +++ b/packages/bun-usockets/src/crypto/root_certs.cpp @@ -5,6 +5,7 @@ #include "./internal/internal.h" #include #include +#include "./default_ciphers.h" static const int root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]); extern "C" void BUN__warn__extra_ca_load_failed(const char* filename, const char* error_msg); @@ -184,3 +185,6 @@ extern "C" X509_STORE *us_get_default_ca_store() { return store; } +extern "C" const char *us_get_default_ciphers() { + return DEFAULT_CIPHER_LIST; +} \ No newline at end of file diff --git a/packages/bun-usockets/src/crypto/root_certs.h b/packages/bun-usockets/src/crypto/root_certs.h index 4fc85d0ffb..7ba5d4f935 100644 --- a/packages/bun-usockets/src/crypto/root_certs.h +++ b/packages/bun-usockets/src/crypto/root_certs.h @@ -1,4 +1,4 @@ -// Maintaining the root certificates +// Maintaining the root certificates // // `src/crypto/root_certs.h` contains a compiled-in set of root certificates used as trust anchors // for TLS certificate validation. @@ -23,76 +23,10 @@ // `src/crypto/root_certs.h`. // * Using `git diff-files` to determine which certificate have been added and/or // removed. -// +// #include "libusockets.h" static struct us_cert_string_t root_certs[] = { -/* GlobalSign Root CA */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMC\n" -"QkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNV\n" -"BAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBa\n" -"MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdS\n" -"b290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUA\n" -"A4IBDwAwggEKAoIBAQDaDuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtI\n" -"K+6NiY6arymAZavpxy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCO\n" -"XkNz8kHp1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n" -"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3\n" -"dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DP\n" -"AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRg\n" -"e2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUFAAOCAQEA1nPnfE920I2/7LqivjTF\n" -"KDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY7\n" -"76BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9\n" -"LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr\n" -"+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n" -"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n" -"-----END CERTIFICATE-----",.len=1258}, - -/* Entrust.net Premium 2048 Secure Server CA */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVz\n" -"dC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJl\n" -"Zi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0\n" -"ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4\n" -"KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0\n" -"Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVm\n" -"LiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl\n" -"ZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp\n" -"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtK\n" -"TY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/EC\n" -"DNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ\n" -"/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUyVYr9smRM\n" -"DuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVC\n" -"wQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/\n" -"BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQAD\n" -"ggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo\n" -"U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6YfzX1XEC+b\n" -"BAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKTJ1wD\n" -"LW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e\n" -"nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=\n" -"-----END CERTIFICATE-----",.len=1501}, - -/* Baltimore CyberTrust Root */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAG\n" -"A1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1v\n" -"cmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjEL\n" -"MAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEi\n" -"MCAGA1UEAxMZQmFsdGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQAD\n" -"ggEPADCCAQoCggEBAKMEuyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2ygu\n" -"zmKiYv60iNoS6zjrIZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo\n" -"6vWrJYeKmpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n" -"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3z\n" -"yZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkC\n" -"AwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1BE3wMBIGA1UdEwEB/wQIMAYB\n" -"Af8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27\n" -"TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukM\n" -"JY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhS\n" -"NzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67\n" -"G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n" -"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n" -"-----END CERTIFICATE-----",.len=1258}, - /* Entrust Root Certification Authority */ {.str="-----BEGIN CERTIFICATE-----\n" "MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAU\n" @@ -119,30 +53,6 @@ static struct us_cert_string_t root_certs[] = { "j2A781q0tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8\n" "-----END CERTIFICATE-----",.len=1639}, -/* Comodo AAA Services root */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UE\n" -"CAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21v\n" -"ZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0\n" -"MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdy\n" -"ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENB\n" -"IExpbWl0ZWQxITAfBgNVBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZI\n" -"hvcNAQEBBQADggEPADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686td\n" -"UIoWMQuaBtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe\n" -"3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8Ioa\n" -"E+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULi\n" -"mAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7S\n" -"w4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYD\n" -"VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDov\n" -"L2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0\n" -"dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG\n" -"9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q\n" -"GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLzRt0vxuBq\n" -"w8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z8VlI\n" -"MCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C\n" -"12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==\n" -"-----END CERTIFICATE-----",.len=1513}, - /* QuoVadis Root CA 2 */ {.str="-----BEGIN CERTIFICATE-----\n" "MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNV\n" @@ -211,78 +121,6 @@ static struct us_cert_string_t root_certs[] = { "zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=\n" "-----END CERTIFICATE-----",.len=2349}, -/* XRamp Global CA Root */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkG\n" -"A1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJh\n" -"bXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlm\n" -"aWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjEL\n" -"MAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMb\n" -"WFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2Vy\n" -"dGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCY\n" -"JB69FbS638eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP\n" -"KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5df\n" -"T2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3\n" -"hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSP\n" -"puIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJ\n" -"KwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O\n" -"BBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwu\n" -"eHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcN\n" -"AQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR\n" -"vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxtqZ4Bfj8p\n" -"zgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8nnxCb\n" -"HIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz\n" -"8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=\n" -"-----END CERTIFICATE-----",.len=1509}, - -/* Go Daddy Class 2 CA */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UE\n" -"ChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAy\n" -"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYy\n" -"MFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjEx\n" -"MC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAw\n" -"DQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWiz\n" -"V3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HF\n" -"iH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi\n" -"EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN\n" -"f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44\n" -"dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLEsNKR1EwRcbNhyz2h/t2oatTj\n" -"MIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2oatTjoWekZTBjMQswCQYDVQQGEwJV\n" -"UzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRk\n" -"eSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJ\n" -"KoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYX\n" -"MP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P\n" -"TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQHmyW74cN\n" -"xA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VILs9R\n" -"aRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b\n" -"vZ8=\n" -"-----END CERTIFICATE-----",.len=1445}, - -/* Starfield Class 2 CA */ -{.str="-----BEGIN CERTIFICATE-----\n" -"MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n" -"ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENs\n" -"YXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5\n" -"MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2ll\n" -"cywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRo\n" -"b3JpdHkwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N\n" -"78gDGIc/oav7PKaf8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMe\n" -"j2YcOadN+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n" -"X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4Umkhyn\n" -"ArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W\n" -"93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRb\n" -"Vazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0fhvRbVazc1xDCDqmI56FspGowaDEL\n" -"MAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAw\n" -"BgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG\n" -"A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1ep\n" -"oXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n" -"eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJlxy16paq8\n" -"U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJDKVtH\n" -"CN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3\n" -"QBFGmh95DmK/D5fs4C8fF5Q=\n" -"-----END CERTIFICATE-----",.len=1465}, - /* DigiCert Assured ID Root CA */ {.str="-----BEGIN CERTIFICATE-----\n" "MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYD\n" @@ -3625,6 +3463,52 @@ static struct us_cert_string_t root_certs[] = { "GJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJhJ65bvspmZDogNOfJA==\n" "-----END CERTIFICATE-----",.len=2020}, +/* TrustAsia TLS ECC Root CA */ +{.str="-----BEGIN CERTIFICATE-----\n" +"MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMwWDELMAkG\n" +"A1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xIjAgBgNV\n" +"BAMTGVRydXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQwNTE1MDU0MTU2WhcNNDQwNTE1\n" +"MDU0MTU1WjBYMQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2ll\n" +"cywgSW5jLjEiMCAGA1UEAxMZVHJ1c3RBc2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49\n" +"AgEGBSuBBAAiA2IABLh/pVs/AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPo\n" +"XlfXTr4sP/MSpwDpguMqWzJ8S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kz\n" +"saNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAw\n" +"DgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01L18N9mds\n" +"d0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15KeAIxAKORh/IRM4PDwYqROkwrULG9IpRdNYlz\n" +"g8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ==\n" +"-----END CERTIFICATE-----",.len=820}, + +/* TrustAsia TLS RSA Root CA */ +{.str="-----BEGIN CERTIFICATE-----\n" +"MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEMBQAwWDEL\n" +"MAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xIjAg\n" +"BgNVBAMTGVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcNMjQwNTE1MDU0MTU3WhcNNDQw\n" +"NTE1MDU0MTU2WjBYMQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xv\n" +"Z2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJ\n" +"KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwha\n" +"GnrhB3YmH49pVr7+NmDQDIPNlOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMm\n" +"SoPGlbYJQ1DNDX3eRA5gEk9bNb2/mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561\n" +"HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fkzv93uMltrOXVmPGZLmzjyUT5tUMnCE32ft5Eebuy\n" +"jBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYozza/+lcK7Fs/6TAWe8TbxNRkoDD75f0dcZLd\n" +"KY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyrz2I8sMeXi9bQn9P+PN7F4/w6g3CEIR0J\n" +"wqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQUNoyIBnkiz/r1RYmNzz7dZ6wB3C4FGB3\n" +"3PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+jTnhMmCWr8n4uIF6CFabW2I+s5c0yhsj55NqJ4js+\n" +"k8UTav/H9xj8Z7XvGCxUq0DTbE3txci3OE9kxJRMT6DNrqXGJyV1J23G2pyOsAWZ1SgRxSHU\n" +"uPzHlqtKZFlhaxP8S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnTq1mt1tve1CuBAgMB\n" +"AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZylomkadFK/hT\n" +"MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3Rz/Nyjuu\n" +"jsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4iqME3mmL5Dw8veWv\n" +"0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt7DlK9RME7I10nYEKqG/odv6L\n" +"TytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp2xIQaOHEibgGIOcberyxk2GaGUARtWqF\n" +"VwHxtlotJnMnlvm5P1vQiJ3koP26TpUJg3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soa\n" +"B82G39tp27RIGAAtvKLEiUUjpQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4\n" +"GS/+X/jbh87qqA8MpugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjE\n" +"Wn9hongPXvPKnbwbPKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIwe\n" +"SsCI3zWQzj8C9GRh3sfIB5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0ly4wBOeY\n" +"99sLAZDBHwo/+ML+TvrbmnNzFrwFuHnYWa8G5z9nODmxfKuU4CkUpijy323imttUQ/hHWKNd\n" +"dBWcwauwxzQ=\n" +"-----END CERTIFICATE-----",.len=1964}, + /* D-TRUST EV Root CA 2 2023 */ {.str="-----BEGIN CERTIFICATE-----\n" "MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBIMQswCQYD\n" @@ -3655,4 +3539,35 @@ static struct us_cert_string_t root_certs[] = { "S5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAstNl7F6cTVg8uGF5cs\n" "bBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phhXBxvWHZks/wCuPWdCg==\n" "-----END CERTIFICATE-----",.len=2020}, + +/* SwissSign RSA TLS Root CA 2022 - 1 */ +{.str="-----BEGIN CERTIFICATE-----\n" +"MIIFkzCCA3ugAwIBAgIUQ/oMX04bgBhE79G0TzUfRPSA7cswDQYJKoZIhvcNAQELBQAwUTEL\n" +"MAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzErMCkGA1UEAxMiU3dpc3NTaWdu\n" +"IFJTQSBUTFMgUm9vdCBDQSAyMDIyIC0gMTAeFw0yMjA2MDgxMTA4MjJaFw00NzA2MDgxMTA4\n" +"MjJaMFExCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxKzApBgNVBAMTIlN3\n" +"aXNzU2lnbiBSU0EgVExTIFJvb3QgQ0EgMjAyMiAtIDEwggIiMA0GCSqGSIb3DQEBAQUAA4IC\n" +"DwAwggIKAoICAQDLKmjiC8NXvDVjvHClO/OMPE5Xlm7DTjak9gLKHqquuN6orx122ro10JFw\n" +"B9+zBvKK8i5VUXu7LCTLf5ImgKO0lPaCoaTo+nUdWfMHamFk4saMla+ju45vVs9xzF6BYQ1t\n" +"8qsCLqSX5XH8irCRIFucdFJtrhUnWXjyCcplDn/L9Ovn3KlMd/YrFgSVrpxxpT8q2kFC5zyE\n" +"EPThPYxr4iuRR1VPuFa+Rd4iUU1OKNlfGUEGjw5NBuBwQCMBauTLE5tzrE0USJIt/m2n+Idr\n" +"eXXhvhCxqohAWVTXz8TQm0SzOGlkjIHRI36qOTw7D59Ke4LKa2/KIj4x0LDQKhySio/YGZxH\n" +"5D4MucLNvkEM+KRHBdvBFzA4OmnczcNpI/2aDwLOEGrOyvi5KaM2iYauC8BPY7kGWUleDsFp\n" +"swrzd34unYyzJ5jSmY0lpx+Gs6ZUcDj8fV3oT4MM0ZPlEuRU2j7yrTrePjxF8CgPBrnh25d7\n" +"mUWe3f6VWQQvdT/TromZhqwUtKiE+shdOxtYk8EXlFXIC+OCeYSf8wCENO7cMdWP8vpPlkwG\n" +"qnj73mSiI80fPsWMvDdUDrtaclXvyFu1cvh43zcgTFeRc5JzrBh3Q4IgaezprClG5QtO+Ddz\n" +"iZaKHG29777YtvTKwP1H8K4LWCDFyB02rpeNUIMmJCn3nTsPBQIDAQABo2MwYTAPBgNVHRMB\n" +"Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBRvjmKLk0Ow4UD2p8P98Q+4\n" +"DxU4pTAdBgNVHQ4EFgQUb45ii5NDsOFA9qfD/fEPuA8VOKUwDQYJKoZIhvcNAQELBQADggIB\n" +"AKwsKUF9+lz1GpUYvyypiqkkVHX1uECry6gkUSsYP2OprphWKwVDIqO310aewCoSPY6WlkDf\n" +"DDOLazeROpW7OSltwAJsipQLBwJNGD77+3v1dj2b9l4wBlgzHqp41eZUBDqyggmNzhYzWUUo\n" +"8aWjlw5DI/0LIICQ/+Mmz7hkkeUFjxOgdg3XNwwQiJb0Pr6VvfHDffCjw3lHC1ySFWPtUnWK\n" +"50Zpy1FVCypM9fJkT6lc/2cyjlUtMoIcgC9qkfjLvH4YoiaoLqNTKIftV+Vlek4ASltOU8li\n" +"Nr3CjlvrzG4ngRhZi0Rjn9UMZfQpZX+RLOV/fuiJz48gy20HQhFRJjKKLjpHE7iNvUcNCfAW\n" +"pO2Whi4Z2L6MOuhFLhG6rlrnub+xzI/goP+4s9GFe3lmozm1O2bYQL7Pt2eLSMkZJVX8vY3P\n" +"XtpOpvJpzv1/THfQwUY1mFwjmwJFQ5Ra3bxHrSL+ul4vkSkphnsh3m5kt8sNjzdbowhq6/Td\n" +"Ao9QAwKxuDdollDruF/UKIqlIgyKhPBZLtU30WHlQnNYKoH3dtvi4k0NX/a3vgW0rk4N3hY9\n" +"A4GzJl5LuEsAz/+MF7psYC0nhzck5npgL7XTgwSqT0N1osGDsieYK7EOgLrAhV5Cud+xYJHT\n" +"6xh+cHiudoO+cVrQkOPKwRYlZ0rwtnu64ZzZ\n" +"-----END CERTIFICATE-----",.len=1988}, }; diff --git a/packages/bun-usockets/src/eventing/epoll_kqueue.c b/packages/bun-usockets/src/eventing/epoll_kqueue.c index 3b6c7e438f..4c59ca6382 100644 --- a/packages/bun-usockets/src/eventing/epoll_kqueue.c +++ b/packages/bun-usockets/src/eventing/epoll_kqueue.c @@ -246,8 +246,7 @@ void us_loop_run(struct us_loop_t *loop) { } } -extern void Bun__JSC_onBeforeWait(void*); -extern void Bun__JSC_onAfterWait(void*); +extern void Bun__JSC_onBeforeWait(void * _Nonnull jsc_vm); void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout) { if (loop->num_polls == 0) @@ -264,8 +263,9 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout /* Emit pre callback */ us_internal_loop_pre(loop); - /* Safe if jsc_vm is NULL */ - Bun__JSC_onBeforeWait(loop->data.jsc_vm); + + if (loop->data.jsc_vm) + Bun__JSC_onBeforeWait(loop->data.jsc_vm); /* Fetch ready polls */ #ifdef LIBUS_USE_EPOLL @@ -276,7 +276,6 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout } while (IS_EINTR(loop->num_ready_polls)); #endif - Bun__JSC_onAfterWait(loop->data.jsc_vm); /* Iterate ready polls, dispatching them by type */ for (loop->current_ready_poll = 0; loop->current_ready_poll < loop->num_ready_polls; loop->current_ready_poll++) { diff --git a/packages/bun-usockets/src/internal/internal.h b/packages/bun-usockets/src/internal/internal.h index 1989d5d58d..360a676954 100644 --- a/packages/bun-usockets/src/internal/internal.h +++ b/packages/bun-usockets/src/internal/internal.h @@ -116,6 +116,8 @@ extern struct addrinfo_result *Bun__addrinfo_getRequestResult(struct addrinfo_re /* Loop related */ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, int events); void us_internal_timer_sweep(us_loop_r loop); +void us_internal_enable_sweep_timer(struct us_loop_t *loop); +void us_internal_disable_sweep_timer(struct us_loop_t *loop); void us_internal_free_closed_sockets(us_loop_r loop); void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context); diff --git a/packages/bun-usockets/src/internal/loop_data.h b/packages/bun-usockets/src/internal/loop_data.h index 3a2186457d..1a950c2372 100644 --- a/packages/bun-usockets/src/internal/loop_data.h +++ b/packages/bun-usockets/src/internal/loop_data.h @@ -35,6 +35,7 @@ typedef void* zig_mutex_t; // IMPORTANT: When changing this, don't forget to update the zig version in uws.zig as well! struct us_internal_loop_data_t { struct us_timer_t *sweep_timer; + int sweep_timer_count; struct us_internal_async *wakeup_async; int last_write_failed; struct us_socket_context_t *head; diff --git a/packages/bun-usockets/src/libusockets.h b/packages/bun-usockets/src/libusockets.h index 7bb0cd0b53..a5156f700c 100644 --- a/packages/bun-usockets/src/libusockets.h +++ b/packages/bun-usockets/src/libusockets.h @@ -262,6 +262,7 @@ enum create_bun_socket_error_t { CREATE_BUN_SOCKET_ERROR_LOAD_CA_FILE, CREATE_BUN_SOCKET_ERROR_INVALID_CA_FILE, CREATE_BUN_SOCKET_ERROR_INVALID_CA, + CREATE_BUN_SOCKET_ERROR_INVALID_CIPHERS, }; struct us_socket_context_t *us_create_bun_ssl_socket_context(struct us_loop_t *loop, diff --git a/packages/bun-usockets/src/loop.c b/packages/bun-usockets/src/loop.c index 7830c5ca47..bcbea5a0ef 100644 --- a/packages/bun-usockets/src/loop.c +++ b/packages/bun-usockets/src/loop.c @@ -18,6 +18,7 @@ #include "libusockets.h" #include "internal/internal.h" #include +#include #ifndef WIN32 #include #endif @@ -29,11 +30,28 @@ extern void __attribute((__noreturn__)) Bun__panic(const char* message, size_t l #define BUN_PANIC(message) Bun__panic(message, sizeof(message) - 1) #endif +void sweep_timer_cb(struct us_internal_callback_t *cb); + +void us_internal_enable_sweep_timer(struct us_loop_t *loop) { + if (loop->data.sweep_timer_count == 0) { + us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000); + } + loop->data.sweep_timer_count++; +} + +void us_internal_disable_sweep_timer(struct us_loop_t *loop) { + loop->data.sweep_timer_count--; + if (loop->data.sweep_timer_count == 0) { + us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, 0, 0); + } +} + /* The loop has 2 fallthrough polls */ void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop), void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop)) { // We allocate with calloc, so we only need to initialize the specific fields in use. loop->data.sweep_timer = us_create_timer(loop, 1, 0); + loop->data.sweep_timer_count = 0; loop->data.recv_buf = malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2); loop->data.send_buf = malloc(LIBUS_SEND_BUFFER_LENGTH); loop->data.pre_cb = pre_cb; @@ -547,9 +565,9 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in } } -/* Integration only requires the timer to be set up */ +/* Integration only requires the timer to be set up, but not automatically enabled */ void us_loop_integrate(struct us_loop_t *loop) { - us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000); + /* Timer is now controlled dynamically by socket count, not enabled automatically */ } void *us_loop_ext(struct us_loop_t *loop) { diff --git a/scripts/build.mjs b/scripts/build.mjs index 1ad5bc577a..d1fab297b6 100755 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -224,6 +224,31 @@ async function spawn(command, args, options, label) { ...options, }); + let killedManually = false; + + function onKill() { + clearOnKill(); + if (!subprocess.killed) { + killedManually = true; + subprocess.kill?.(); + } + } + + function clearOnKill() { + process.off("beforeExit", onKill); + process.off("SIGINT", onKill); + process.off("SIGTERM", onKill); + } + + // Kill the entire process tree so everything gets cleaned up. On Windows, job + // control groups make this haappen automatically so we don't need to do this + // on Windows. + if (process.platform !== "win32") { + process.once("beforeExit", onKill); + process.once("SIGINT", onKill); + process.once("SIGTERM", onKill); + } + let timestamp; subprocess.on("spawn", () => { timestamp = Date.now(); @@ -253,8 +278,14 @@ async function spawn(command, args, options, label) { } const { error, exitCode, signalCode } = await new Promise(resolve => { - subprocess.on("error", error => resolve({ error })); - subprocess.on("exit", (exitCode, signalCode) => resolve({ exitCode, signalCode })); + subprocess.on("error", error => { + clearOnKill(); + resolve({ error }); + }); + subprocess.on("exit", (exitCode, signalCode) => { + clearOnKill(); + resolve({ exitCode, signalCode }); + }); }); if (done) { @@ -301,7 +332,9 @@ async function spawn(command, args, options, label) { } if (signalCode) { - console.error(`Command killed: ${signalCode}`); + if (!killedManually) { + console.error(`Command killed: ${signalCode}`); + } } else { console.error(`Command exited: code ${exitCode}`); } diff --git a/scripts/lldb-inline-tool.cpp b/scripts/lldb-inline-tool.cpp new file mode 100644 index 0000000000..597c9c4d5e --- /dev/null +++ b/scripts/lldb-inline-tool.cpp @@ -0,0 +1,409 @@ +/* + * LLDB Inline Debug Tool + * + * This tool allows you to add inline debug points in your code using comments: + * // LOG: message here + * // LOG: variable value is {variable_name} + * + * The tool will set non-stopping breakpoints at these locations and print + * the messages when hit, without interrupting program execution. + * + * BUILD INSTRUCTIONS: + * ------------------ + * On macOS with Homebrew LLVM: + * c++ -std=c++17 -o lldb-inline lldb-inline-tool.cpp \ + * -llldb \ + * -L/opt/homebrew/opt/llvm/lib \ + * -I/opt/homebrew/opt/llvm/include \ + * -Wl,-rpath,/opt/homebrew/opt/llvm/lib + * + * On Linux: + * c++ -std=c++17 -o lldb-inline lldb-inline-tool.cpp \ + * -llldb \ + * -L/usr/lib/llvm-14/lib \ + * -I/usr/lib/llvm-14/include + * + * USAGE: + * ------ + * ./lldb-inline [args...] + * + * The tool searches for // LOG: comments in all source files listed in + * cmake/sources/ *.txt and sets breakpoints at those locations. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char **environ; + +using namespace lldb; + +struct DebugPoint { + std::string file; + int line; + int column; + enum Type { LOG, VAR } type; + std::string data; +}; + +std::vector debugPoints; + +bool logpointCallback(void *baton, SBProcess &process, SBThread &thread, SBBreakpointLocation &location) { + auto start = std::chrono::high_resolution_clock::now(); + + auto* point = static_cast(baton); + + std::cout << point->file << ":" << point->line << ":" << point->column << " "; + + // Parse the log message for {expressions} + std::string msg = point->data; + size_t pos = 0; + + while ((pos = msg.find('{', pos)) != std::string::npos) { + size_t endPos = msg.find('}', pos); + if (endPos == std::string::npos) { + break; + } + + // Extract expression + std::string expr = msg.substr(pos + 1, endPos - pos - 1); + + // Evaluate expression + SBFrame frame = thread.GetFrameAtIndex(0); + SBValue result = frame.EvaluateExpression(expr.c_str()); + + std::string value; + if (result.GetError().Success() && result.GetValue()) { + value = result.GetValue(); + } else { + value = ""; + } + + // Replace {expression} with value + msg.replace(pos, endPos - pos + 1, value); + pos += value.length(); + } + + std::cout << msg << std::endl; + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + // std::cerr << "Breakpoint callback took: " << duration.count() << "ms" << std::endl; + + // Don't stop + return false; +} + +std::vector getSourceFiles() { + std::vector files; + + // Read cmake source files + glob_t globbuf; + if (glob("cmake/sources/*.txt", 0, nullptr, &globbuf) == 0) { + for (size_t i = 0; i < globbuf.gl_pathc; i++) { + std::ifstream file(globbuf.gl_pathv[i]); + std::string line; + while (std::getline(file, line)) { + if (!line.empty() && line[0] != '#' && line.find("${") == std::string::npos) { + files.push_back(line); + } + } + } + globfree(&globbuf); + } + + return files; +} + +void findDebugPoints() { + // Get source files + auto files = getSourceFiles(); + + if (files.empty()) { + return; + } + + // Create temp file with list of files + std::string tmpfile = "/tmp/lldb-inline-files.txt"; + std::ofstream out(tmpfile); + for (const auto& file : files) { + out << file << std::endl; + } + out.close(); + + // Use ripgrep with limited threads for speed + std::string cmd = "cat " + tmpfile + " | xargs rg -j4 --line-number --column --no-heading --color=never '//\\s*LOG:'"; + + FILE* pipe = popen(cmd.c_str(), "r"); + if (!pipe) { + unlink(tmpfile.c_str()); + return; + } + + char buffer[1024]; + std::regex logRegex(".*//\\s*LOG:\\s*(.+)"); + + while (fgets(buffer, sizeof(buffer), pipe)) { + std::string line(buffer); + // Remove trailing newline + if (!line.empty() && line.back() == '\n') { + line.pop_back(); + } + + // Parse ripgrep output: file:line:column:text + size_t pos1 = line.find(':'); + if (pos1 == std::string::npos) continue; + + size_t pos2 = line.find(':', pos1 + 1); + if (pos2 == std::string::npos) continue; + + size_t pos3 = line.find(':', pos2 + 1); + if (pos3 == std::string::npos) continue; + + DebugPoint point; + point.file = line.substr(0, pos1); + point.line = std::stoi(line.substr(pos1 + 1, pos2 - pos1 - 1)); + point.column = std::stoi(line.substr(pos2 + 1, pos3 - pos2 - 1)); + + std::string text = line.substr(pos3 + 1); + + std::smatch match; + if (std::regex_match(text, match, logRegex)) { + point.type = DebugPoint::LOG; + point.data = match[1]; // The message is in capture group 1 + // Trim whitespace + point.data.erase(0, point.data.find_first_not_of(" \t")); + point.data.erase(point.data.find_last_not_of(" \t") + 1); + debugPoints.push_back(point); + } + } + + pclose(pipe); + unlink(tmpfile.c_str()); +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + return 1; + } + + const char* executable = argv[1]; + + // Find debug points + auto start = std::chrono::high_resolution_clock::now(); + findDebugPoints(); + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + // std::cerr << "Ripgrep search took: " << duration.count() << "ms" << std::endl; + + + if (debugPoints.empty()) { + return 1; + } + + // Initialize LLDB + start = std::chrono::high_resolution_clock::now(); + SBDebugger::Initialize(); + SBDebugger debugger = SBDebugger::Create(false); // Don't read .lldbinit + debugger.SetAsync(true); + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - start); + // std::cerr << "LLDB init took: " << duration.count() << "ms" << std::endl; + + // Keep LLDB's stdio handling enabled + SBCommandInterpreter interpreter = debugger.GetCommandInterpreter(); + SBCommandReturnObject result; + interpreter.HandleCommand("settings set target.disable-stdio false", result); + interpreter.HandleCommand("settings set symbols.load-on-demand true", result); + interpreter.HandleCommand("settings set target.preload-symbols false", result); + interpreter.HandleCommand("settings set symbols.enable-external-lookup false", result); + interpreter.HandleCommand("settings set target.auto-import-clang-modules false", result); + interpreter.HandleCommand("settings set target.detach-on-error true", result); + + // Create target + SBError error; + char cwd[PATH_MAX]; + getcwd(cwd, sizeof(cwd)); + + std::string fullPath = executable; + if (fullPath[0] != '/') { + fullPath = std::string(cwd) + "/" + executable; + } + + start = std::chrono::high_resolution_clock::now(); + SBTarget target = debugger.CreateTarget(fullPath.c_str(), nullptr, nullptr, false, error); + if (!target.IsValid()) { + std::cerr << "Failed to create target: " << error.GetCString() << std::endl; + return 1; + } + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - start); + // std::cerr << "Create target took: " << duration.count() << "ms" << std::endl; + + // Set breakpoints + start = std::chrono::high_resolution_clock::now(); + for (auto& point : debugPoints) { + std::string absPath = point.file; + if (absPath[0] != '/') { + absPath = std::string(cwd) + "/" + point.file; + } + + SBBreakpoint bp = target.BreakpointCreateByLocation(absPath.c_str(), point.line); + if (bp.IsValid()) { + bp.SetCallback(logpointCallback, &point); + } + } + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - start); + // std::cerr << "Set breakpoints took: " << duration.count() << "ms" << std::endl; + + // Build args + std::vector args; + for (int i = 2; i < argc; i++) { + args.push_back(argv[i]); + } + args.push_back(nullptr); + + // Launch process with proper settings + SBLaunchInfo launch_info(args.data()); + launch_info.SetWorkingDirectory(cwd); + launch_info.SetLaunchFlags(0); // Don't disable stdio + + // Pass through environment variables from parent + SBEnvironment env = launch_info.GetEnvironment(); + for (char **p = environ; *p != nullptr; p++) { + env.PutEntry(*p); + } + launch_info.SetEnvironment(env, false); + + start = std::chrono::high_resolution_clock::now(); + SBProcess process = target.Launch(launch_info, error); + if (!process.IsValid()) { + std::cerr << "Failed to launch process: " << error.GetCString() << std::endl; + return 1; + } + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - start); + // std::cerr << "Launch process took: " << duration.count() << "ms" << std::endl; + + // lldb::pid_t launchedPid = process.GetProcessID(); + // std::cerr << "Launched process with PID: " << launchedPid << std::endl; + + // Handle events properly + SBListener listener = debugger.GetListener(); + + start = std::chrono::high_resolution_clock::now(); + auto lastOutput = start; + bool done = false; + bool gotOutput = false; + + int eventCount = 0; + while (!done) { + SBEvent event; + if (listener.WaitForEvent(0, event)) { // Non-blocking + eventCount++; + auto eventTime = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(eventTime - start); + StateType state = SBProcess::GetStateFromEvent(event); + // std::cerr << "Event #" << eventCount << " at " << elapsed.count() << "ms: state=" << state << std::endl; + if (state == eStateExited) { + auto exitTime = std::chrono::high_resolution_clock::now(); + auto totalTime = std::chrono::duration_cast(exitTime - start); + // std::cerr << "Process exited with code: " << process.GetExitStatus() << " after " << totalTime.count() << "ms in event loop" << std::endl; + } + + switch (state) { + case eStateStopped: + process.Continue(); + break; + + case eStateRunning: + break; + + case eStateExited: + case eStateCrashed: + case eStateDetached: + // std::cerr << "Exiting immediately on state: " << state << std::endl; + // Just exit immediately - skip all cleanup + exit(process.GetExitStatus()); + break; + + default: + break; + } + } else { + // No event, check if process is done + StateType currentState = process.GetState(); + if (currentState == eStateExited || currentState == eStateCrashed || currentState == eStateDetached) { + done = true; + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - lastOutput); + // std::cerr << "Process already exited, detected by polling. Time from last output: " << duration.count() << "ms" << std::endl; + } + } + + // Read and forward stdout/stderr + char buffer[1024]; + size_t num_bytes; + + bool hadStdout = false; + while ((num_bytes = process.GetSTDOUT(buffer, sizeof(buffer)-1)) > 0) { + buffer[num_bytes] = '\0'; + std::cout << buffer; + std::cout.flush(); + lastOutput = std::chrono::high_resolution_clock::now(); + gotOutput = true; + hadStdout = true; + } + + bool hadStderr = false; + while ((num_bytes = process.GetSTDERR(buffer, sizeof(buffer)-1)) > 0) { + buffer[num_bytes] = '\0'; + std::cerr << buffer; + std::cerr.flush(); + lastOutput = std::chrono::high_resolution_clock::now(); + gotOutput = true; + hadStderr = true; + } + + // Poll process state every iteration + StateType currentState = process.GetState(); + if (currentState == eStateExited || currentState == eStateCrashed || currentState == eStateDetached) { + // Process has exited, break out of loop + done = true; + } else { + // Small sleep to avoid busy-waiting + usleep(10000); // 10ms + } + } + + int exit_code = process.GetExitStatus(); + + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - start); + // std::cerr << "Total event loop time: " << duration.count() << "ms" << std::endl; + + // Cleanup + start = std::chrono::high_resolution_clock::now(); + SBDebugger::Destroy(debugger); + end = std::chrono::high_resolution_clock::now(); + duration = std::chrono::duration_cast(end - start); + // std::cerr << "Debugger destroy took: " << duration.count() << "ms" << std::endl; + + SBDebugger::Terminate(); + + return exit_code; +} \ No newline at end of file diff --git a/scripts/lldb-inline.sh b/scripts/lldb-inline.sh new file mode 100755 index 0000000000..13dcd2c529 --- /dev/null +++ b/scripts/lldb-inline.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# LLDB Inline Debug Tool Build & Run Script +# +# This script builds the lldb-inline tool if needed and runs it. +# Usage: ./scripts/lldb-inline.sh [args...] + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TOOL_SOURCE="$SCRIPT_DIR/lldb-inline-tool.cpp" +TOOL_BINARY="$SCRIPT_DIR/lldb-inline" + +# Check if we need to rebuild +if [ ! -f "$TOOL_BINARY" ] || [ "$TOOL_SOURCE" -nt "$TOOL_BINARY" ]; then + # Detect OS and build accordingly + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS with Homebrew LLVM + c++ -std=c++17 -o "$TOOL_BINARY" "$TOOL_SOURCE" \ + -llldb \ + -L/opt/homebrew/opt/llvm/lib \ + -I/opt/homebrew/opt/llvm/include \ + -Wl,-rpath,/opt/homebrew/opt/llvm/lib >/dev/null 2>&1 + else + # Linux - try to find LLVM installation + LLVM_DIR="" + for version in 18 17 16 15 14 13 12; do + if [ -d "/usr/lib/llvm-$version" ]; then + LLVM_DIR="/usr/lib/llvm-$version" + break + fi + done + + if [ -z "$LLVM_DIR" ] && [ -d "/usr/lib/llvm" ]; then + LLVM_DIR="/usr/lib/llvm" + fi + + if [ -z "$LLVM_DIR" ]; then + # Try pkg-config as fallback + LLDB_CFLAGS=$(pkg-config --cflags lldb 2>/dev/null) + LLDB_LIBS=$(pkg-config --libs lldb 2>/dev/null) + c++ -std=c++17 -o "$TOOL_BINARY" "$TOOL_SOURCE" \ + $LLDB_CFLAGS $LLDB_LIBS >/dev/null 2>&1 + else + c++ -std=c++17 -o "$TOOL_BINARY" "$TOOL_SOURCE" \ + -llldb \ + -L"$LLVM_DIR/lib" \ + -I"$LLVM_DIR/include" >/dev/null 2>&1 + fi + fi + + if [ $? -ne 0 ]; then + exit 1 + fi +fi + +# Run the tool with all arguments +exec "$TOOL_BINARY" "$@" \ No newline at end of file diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index d3e108083a..aa514ba8d1 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -74,7 +74,6 @@ const testsPath = join(cwd, "test"); const spawnTimeout = 5_000; const testTimeout = 3 * 60_000; const integrationTimeout = 5 * 60_000; -const napiTimeout = 10 * 60_000; function getNodeParallelTestTimeout(testPath) { if (testPath.includes("test-dns")) { @@ -271,6 +270,7 @@ const skipArray = (() => { } return readFileSync(path, "utf-8") .split("\n") + .map(line => line.trim()) .filter(line => !line.startsWith("#") && line.length > 0); })(); @@ -471,38 +471,45 @@ async function runTests() { } if (!failedResults.length) { - // bun install has succeeded - const { promise: portPromise, resolve: portResolve } = Promise.withResolvers(); - const { promise: errorPromise, resolve: errorResolve } = Promise.withResolvers(); - console.log("run in", cwd); - let exiting = false; + // TODO: remove windows exclusion here + if (isCI && !isWindows) { + // bun install has succeeded + const { promise: portPromise, resolve: portResolve } = Promise.withResolvers(); + const { promise: errorPromise, resolve: errorResolve } = Promise.withResolvers(); + console.log("run in", cwd); + let exiting = false; - const server = spawn(execPath, ["run", "ci-remap-server", execPath, cwd, getCommit()], { - stdio: ["ignore", "pipe", "inherit"], - cwd, // run in main repo - env: { ...process.env, BUN_DEBUG_QUIET_LOGS: "1", NO_COLOR: "1" }, - }); - server.unref(); - server.on("error", errorResolve); - server.on("exit", (code, signal) => { - if (!exiting && (code !== 0 || signal !== null)) errorResolve(signal ? signal : "code " + code); - }); - process.on("exit", () => { - exiting = true; - server.kill(); - }); - const lines = createInterface(server.stdout); - lines.on("line", line => { - portResolve({ port: parseInt(line) }); - }); + const server = spawn(execPath, ["run", "--silent", "ci-remap-server", execPath, cwd, getCommit()], { + stdio: ["ignore", "pipe", "inherit"], + cwd, // run in main repo + env: { ...process.env, BUN_DEBUG_QUIET_LOGS: "1", NO_COLOR: "1" }, + }); + server.unref(); + server.on("error", errorResolve); + server.on("exit", (code, signal) => { + if (!exiting && (code !== 0 || signal !== null)) errorResolve(signal ? signal : "code " + code); + }); + function onBeforeExit() { + exiting = true; + server.off("error"); + server.off("exit"); + server.kill?.(); + } + process.once("beforeExit", onBeforeExit); + const lines = createInterface(server.stdout); + lines.on("line", line => { + portResolve({ port: parseInt(line) }); + }); - const result = await Promise.race([portPromise, errorPromise, setTimeoutPromise(5000, "timeout")]); - if (typeof result.port != "number") { - server.kill(); - console.warn("ci-remap server did not start:", result); - } else { - console.log("crash reports parsed on port", result.port); - remapPort = result.port; + const result = await Promise.race([portPromise, errorPromise.catch(e => e), setTimeoutPromise(5000, "timeout")]); + if (typeof result?.port != "number") { + process.off("beforeExit", onBeforeExit); + server.kill?.(); + console.warn("ci-remap server did not start:", result); + } else { + console.log("crash reports parsed on port", result.port); + remapPort = result.port; + } } await Promise.all( @@ -1286,9 +1293,6 @@ function getTestTimeout(testPath) { if (/integration|3rd_party|docker|bun-install-registry|v8/i.test(testPath)) { return integrationTimeout; } - if (/napi/i.test(testPath) || /v8/i.test(testPath)) { - return napiTimeout; - } return testTimeout; } diff --git a/src/Global.zig b/src/Global.zig index 063fc78084..9ec3db85b2 100644 --- a/src/Global.zig +++ b/src/Global.zig @@ -165,13 +165,7 @@ pub const versions = @import("./generated_versions_list.zig"); // Keeping this code for: // 1. documentation that an attempt was made // 2. if I want to configure allocator later -pub inline fn configureAllocator(_: AllocatorConfiguration) void { - // if (comptime !use_mimalloc) return; - // const mimalloc = bun.mimalloc; - // mimalloc.mi_option_set_enabled(mimalloc.mi_option_verbose, config.verbose); - // mimalloc.mi_option_set_enabled(mimalloc.mi_option_large_os_pages, config.long_running); - // if (!config.long_running) mimalloc.mi_option_set(mimalloc.mi_option_reset_delay, 0); -} +pub inline fn configureAllocator(_: AllocatorConfiguration) void {} pub fn notimpl() noreturn { @branchHint(.cold); diff --git a/src/allocators/AllocationScope.zig b/src/allocators/AllocationScope.zig index 324468dd03..a37e3fa555 100644 --- a/src/allocators/AllocationScope.zig +++ b/src/allocators/AllocationScope.zig @@ -216,7 +216,7 @@ pub fn trackExternalAllocation(scope: *AllocationScope, ptr: []const u8, ret_add /// Call when the pointer from `trackExternalAllocation` is freed. /// Returns true if the free was invalid. pub fn trackExternalFree(scope: *AllocationScope, slice: anytype, ret_addr: ?usize) bool { - if (comptime !enabled) return; + if (comptime !enabled) return false; const ptr: []const u8 = switch (@typeInfo(@TypeOf(slice))) { .pointer => |p| switch (p.size) { .slice => brk: { diff --git a/src/allocators/MimallocArena.zig b/src/allocators/MimallocArena.zig index 1d33cf3dd2..718949d1db 100644 --- a/src/allocators/MimallocArena.zig +++ b/src/allocators/MimallocArena.zig @@ -72,7 +72,7 @@ pub const supports_posix_memalign = true; fn alignedAlloc(heap: *mimalloc.Heap, len: usize, alignment: mem.Alignment) ?[*]u8 { log("Malloc: {d}\n", .{len}); - const ptr: ?*anyopaque = if (mimalloc.canUseAlignedAlloc(len, alignment.toByteUnits())) + const ptr: ?*anyopaque = if (mimalloc.mustUseAlignedAlloc(alignment)) mimalloc.mi_heap_malloc_aligned(heap, len, alignment.toByteUnits()) else mimalloc.mi_heap_malloc(heap, len); @@ -119,7 +119,7 @@ fn free( // but its good to have that assertion if (comptime Environment.isDebug) { assert(mimalloc.mi_is_in_heap_region(buf.ptr)); - if (mimalloc.canUseAlignedAlloc(buf.len, alignment.toByteUnits())) + if (mimalloc.mustUseAlignedAlloc(alignment)) mimalloc.mi_free_size_aligned(buf.ptr, buf.len, alignment.toByteUnits()) else mimalloc.mi_free_size(buf.ptr, buf.len); diff --git a/src/allocators/NullableAllocator.zig b/src/allocators/NullableAllocator.zig index 1bcafd5529..6ebe10d98b 100644 --- a/src/allocators/NullableAllocator.zig +++ b/src/allocators/NullableAllocator.zig @@ -30,8 +30,8 @@ pub inline fn get(this: NullableAllocator) ?std.mem.Allocator { pub fn free(this: *const NullableAllocator, bytes: []const u8) void { if (this.get()) |allocator| { if (bun.String.isWTFAllocator(allocator)) { - // workaround for https://github.com/ziglang/zig/issues/4298 - bun.String.StringImplAllocator.free(allocator.ptr, @constCast(bytes), .fromByteUnits(1), 0); + // avoid calling `std.mem.Allocator.free` as it sets the memory to undefined + allocator.rawFree(@constCast(bytes), .@"1", 0); return; } diff --git a/src/allocators/basic.zig b/src/allocators/basic.zig index 44a4b99998..916d1871e4 100644 --- a/src/allocators/basic.zig +++ b/src/allocators/basic.zig @@ -13,8 +13,7 @@ fn mimalloc_free( // but its good to have that assertion // let's only enable it in debug mode if (comptime Environment.isDebug) { - assert(mimalloc.mi_is_in_heap_region(buf.ptr)); - if (mimalloc.canUseAlignedAlloc(buf.len, alignment.toByteUnits())) + if (mimalloc.mustUseAlignedAlloc(alignment)) mimalloc.mi_free_size_aligned(buf.ptr, buf.len, alignment.toByteUnits()) else mimalloc.mi_free_size(buf.ptr, buf.len); @@ -25,12 +24,11 @@ fn mimalloc_free( const MimallocAllocator = struct { pub const supports_posix_memalign = true; - fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 { if (comptime Environment.enable_logs) log("mi_alloc({d}, {d})", .{ len, alignment.toByteUnits() }); - const ptr: ?*anyopaque = if (mimalloc.canUseAlignedAlloc(len, alignment.toByteUnits())) + const ptr: ?*anyopaque = if (mimalloc.mustUseAlignedAlloc(alignment)) mimalloc.mi_malloc_aligned(len, alignment.toByteUnits()) else mimalloc.mi_malloc(len); @@ -84,7 +82,7 @@ const ZAllocator = struct { fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 { log("ZAllocator.alignedAlloc: {d}\n", .{len}); - const ptr = if (mimalloc.canUseAlignedAlloc(len, alignment.toByteUnits())) + const ptr = if (mimalloc.mustUseAlignedAlloc(alignment)) mimalloc.mi_zalloc_aligned(len, alignment.toByteUnits()) else mimalloc.mi_zalloc(len); @@ -148,7 +146,6 @@ const Environment = @import("../env.zig"); const std = @import("std"); const bun = @import("bun"); -const assert = bun.assert; const mimalloc = bun.mimalloc; const mem = @import("std").mem; diff --git a/src/allocators/mimalloc.zig b/src/allocators/mimalloc.zig index 2fa101d04e..88fce6b8a3 100644 --- a/src/allocators/mimalloc.zig +++ b/src/allocators/mimalloc.zig @@ -127,39 +127,58 @@ pub extern fn mi_reserve_huge_os_pages_at(pages: usize, numa_node: c_int, timeou pub extern fn mi_reserve_os_memory(size: usize, commit: bool, allow_large: bool) c_int; pub extern fn mi_manage_os_memory(start: ?*anyopaque, size: usize, is_committed: bool, is_large: bool, is_zero: bool, numa_node: c_int) bool; pub extern fn mi_debug_show_arenas() void; -pub const ArenaID = c_int; -pub extern fn mi_arena_area(arena_id: ArenaID, size: [*c]usize) ?*anyopaque; +pub const ArenaID = ?*anyopaque; +pub extern fn mi_arena_area(arena_id: ArenaID, size: *usize) ?*anyopaque; pub extern fn mi_reserve_huge_os_pages_at_ex(pages: usize, numa_node: c_int, timeout_msecs: usize, exclusive: bool, arena_id: *ArenaID) c_int; pub extern fn mi_reserve_os_memory_ex(size: usize, commit: bool, allow_large: bool, exclusive: bool, arena_id: *ArenaID) c_int; pub extern fn mi_manage_os_memory_ex(start: ?*anyopaque, size: usize, is_committed: bool, is_large: bool, is_zero: bool, numa_node: c_int, exclusive: bool, arena_id: *ArenaID) bool; pub extern fn mi_heap_new_in_arena(arena_id: ArenaID) ?*Heap; pub extern fn mi_reserve_huge_os_pages(pages: usize, max_secs: f64, pages_reserved: [*c]usize) c_int; +pub extern fn mi_thread_set_in_threadpool() void; pub const Option = enum(c_uint) { show_errors = 0, show_stats = 1, verbose = 2, eager_commit = 3, - deprecated_eager_region_commit = 4, - deprecated_reset_decommits = 5, - large_os_pages = 6, + arena_eager_commit = 4, + purge_decommits = 5, + allow_large_os_pages = 6, reserve_huge_os_pages = 7, reserve_huge_os_pages_at = 8, reserve_os_memory = 9, deprecated_segment_cache = 10, - page_reset = 11, - abandoned_page_decommit = 12, + deprecated_page_reset = 11, + abandoned_page_purge = 12, deprecated_segment_reset = 13, eager_commit_delay = 14, - decommit_delay = 15, + purge_delay = 15, use_numa_nodes = 16, - limit_os_alloc = 17, + disallow_os_alloc = 17, os_tag = 18, max_errors = 19, max_warnings = 20, - max_segment_reclaim = 21, - allow_decommit = 22, - segment_decommit_delay = 23, - decommit_extend_delay = 24, + deprecated_max_segment_reclaim = 21, + destroy_on_exit = 22, + arena_reserve = 23, + arena_purge_mult = 24, + deprecated_purge_extend_delay = 25, + disallow_arena_alloc = 26, + retry_on_oom = 27, + visit_abandoned = 28, + guarded_min = 29, + guarded_max = 30, + guarded_precise = 31, + guarded_sample_rate = 32, + guarded_sample_seed = 33, + generic_collect = 34, + page_reclaim_on_free = 35, + page_full_retain = 36, + page_max_candidates = 37, + max_vabits = 38, + pagemap_commit = 39, + page_commit_on_demand = 40, + page_max_reclaim = 41, + page_cross_thread_max_reclaim = 42, }; pub extern fn mi_option_is_enabled(option: Option) bool; pub extern fn mi_option_enable(option: Option) void; @@ -202,13 +221,13 @@ pub const MI_SMALL_WSIZE_MAX = @as(c_int, 128); pub const MI_SMALL_SIZE_MAX = MI_SMALL_WSIZE_MAX * @import("std").zig.c_translation.sizeof(?*anyopaque); pub const MI_ALIGNMENT_MAX = (@as(c_int, 16) * @as(c_int, 1024)) * @as(c_ulong, 1024); -pub fn canUseAlignedAlloc(len: usize, alignment: usize) bool { - return alignment > 0 and std.math.isPowerOfTwo(alignment) and !mi_malloc_satisfies_alignment(alignment, len); -} const MI_MAX_ALIGN_SIZE = 16; -inline fn mi_malloc_satisfies_alignment(alignment: usize, size: usize) bool { - return (alignment == @sizeOf(*anyopaque) or - (alignment == MI_MAX_ALIGN_SIZE and size >= (MI_MAX_ALIGN_SIZE / 2))); + +pub fn mustUseAlignedAlloc(alignment: std.mem.Alignment) bool { + return alignment.toByteUnits() > MI_MAX_ALIGN_SIZE; } +pub const mi_arena_id_t = ?*anyopaque; +pub extern fn mi_heap_new_ex(heap_tag: c_int, allow_destroy: bool, arena_id: mi_arena_id_t) ?*Heap; + const std = @import("std"); diff --git a/src/asan.zig b/src/asan.zig new file mode 100644 index 0000000000..d5badee519 --- /dev/null +++ b/src/asan.zig @@ -0,0 +1,93 @@ +/// https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/sanitizer/asan_interface.h +const c = if (bun.Environment.enable_asan) struct { + extern fn __asan_poison_memory_region(ptr: *const anyopaque, size: usize) void; + extern fn __asan_unpoison_memory_region(ptr: *const anyopaque, size: usize) void; + extern fn __asan_address_is_poisoned(ptr: *const anyopaque) bool; + extern fn __asan_describe_address(ptr: *const anyopaque) void; + extern fn __asan_update_allocation_context(ptr: *const anyopaque) c_int; + + pub fn poison(ptr: *const anyopaque, size: usize) void { + __asan_poison_memory_region(ptr, size); + } + pub fn unpoison(ptr: *const anyopaque, size: usize) void { + __asan_unpoison_memory_region(ptr, size); + } + pub fn isPoisoned(ptr: *const anyopaque) bool { + return __asan_address_is_poisoned(ptr); + } + pub fn describe(ptr: *const anyopaque) void { + __asan_describe_address(ptr); + } + pub fn updateAllocationContext(ptr: *const anyopaque) c_int { + return __asan_update_allocation_context(ptr); + } +} else struct { + pub fn poison(_: *const anyopaque) void {} + pub fn unpoison(_: *const anyopaque) void {} + pub fn isPoisoned(_: *const anyopaque) bool { + return false; + } + pub fn describe(_: *const anyopaque) void {} + pub fn updateAllocationContext(_: *const anyopaque) c_int { + return 0; + } +}; + +pub const enabled = bun.Environment.enable_asan; + +/// Update allocation stack trace for the given allocation to the current stack +/// trace +pub fn updateAllocationContext(ptr: *const anyopaque) bool { + if (!comptime enabled) return false; + return c.updateAllocationContext(ptr) == 1; +} + +/// Describes an address (prints out where it was allocated, freed, stacktraces, +/// etc.) +pub fn describe(ptr: *const anyopaque) void { + if (!comptime enabled) return; + c.describe(ptr); +} + +/// Manually poison a memory region +/// +/// Useful for making custom allocators asan-aware (for example HiveArray) +/// +/// *NOT* threadsafe +pub fn poison(ptr: *const anyopaque, size: usize) void { + if (!comptime enabled) return; + c.poison(ptr, size); +} + +/// Manually unpoison a memory region +/// +/// Useful for making custom allocators asan-aware (for example HiveArray) +/// +/// *NOT* threadsafe +pub fn unpoison(ptr: *const anyopaque, size: usize) void { + if (!comptime enabled) return; + c.unpoison(ptr, size); +} + +fn isPoisoned(ptr: *const anyopaque) bool { + if (!comptime enabled) return false; + return c.isPoisoned(ptr); +} + +pub fn assertPoisoned(ptr: *const anyopaque) void { + if (!comptime enabled) return; + if (!isPoisoned(ptr)) { + c.describe(ptr); + @panic("Address is not poisoned"); + } +} + +pub fn assertUnpoisoned(ptr: *const anyopaque) void { + if (!comptime enabled) return; + if (isPoisoned(ptr)) { + c.describe(ptr); + @panic("Address is poisoned"); + } +} + +const bun = @import("bun"); diff --git a/src/ast/E.zig b/src/ast/E.zig index 0f7c94089a..2e134aea62 100644 --- a/src/ast/E.zig +++ b/src/ast/E.zig @@ -925,7 +925,6 @@ pub const String = struct { pub fn resolveRopeIfNeeded(this: *String, allocator: std.mem.Allocator) void { if (this.next == null or !this.isUTF8()) return; var bytes = std.ArrayList(u8).initCapacity(allocator, this.rope_len) catch bun.outOfMemory(); - bytes.appendSliceAssumeCapacity(this.data); var str = this.next; while (str) |part| { diff --git a/src/ast/Expr.zig b/src/ast/Expr.zig index 9d5d1def34..a8b3d60b09 100644 --- a/src/ast/Expr.zig +++ b/src/ast/Expr.zig @@ -96,7 +96,7 @@ pub fn fromBlob( if (mime_type.category.isTextLike()) { var output = MutableString.initEmpty(allocator); - output = try JSPrinter.quoteForJSON(bytes, output, true); + try JSPrinter.quoteForJSON(bytes, &output, true); var list = output.toOwnedSlice(); // remove the quotes if (list.len > 0) { diff --git a/src/bake/DevServer.zig b/src/bake/DevServer.zig index f8a4f230b7..78c63069be 100644 --- a/src/bake/DevServer.zig +++ b/src/bake/DevServer.zig @@ -205,8 +205,7 @@ deferred_request_pool: bun.HiveArray(DeferredRequest.Node, DeferredRequest.max_p /// UWS can handle closing the websocket connections themselves active_websocket_connections: std.AutoHashMapUnmanaged(*HmrSocket, void), -relative_path_buf_lock: bun.DebugThreadLock, -relative_path_buf: bun.PathBuffer, +relative_path_buf: DebugGuardedValue(bun.PathBuffer), // Debugging @@ -325,7 +324,6 @@ pub fn init(options: Options) bun.JSOOM!*DevServer { true else bun.getRuntimeFeatureFlag(.BUN_ASSUME_PERFECT_INCREMENTAL), - .relative_path_buf_lock = .unlocked, .testing_batch_events = .disabled, .broadcast_console_log_from_browser_to_server = options.broadcast_console_log_from_browser_to_server, .server_transpiler = undefined, @@ -337,7 +335,7 @@ pub fn init(options: Options) bun.JSOOM!*DevServer { .watcher_atomics = undefined, .log = undefined, .deferred_request_pool = undefined, - .relative_path_buf = undefined, + .relative_path_buf = .init(undefined, bun.DebugThreadLock.unlocked), }); errdefer bun.destroy(dev); const allocator = dev.allocation_scope.allocator(); @@ -537,10 +535,13 @@ pub fn init(options: Options) bun.JSOOM!*DevServer { if (bun.FeatureFlags.bake_debugging_features and dev.has_pre_crash_handler) try bun.crash_handler.appendPreCrashHandler(DevServer, dev, dumpStateDueToCrash); + bun.assert(dev.magic == .valid); + return dev; } pub fn deinit(dev: *DevServer) void { + debug.log("deinit", .{}); dev_server_deinit_count_for_testing +|= 1; const allocator = dev.allocator; @@ -561,7 +562,6 @@ pub fn deinit(dev: *DevServer) void { .frontend_only = {}, .generation = {}, .plugin_state = {}, - .relative_path_buf_lock = {}, .root = {}, .server = {}, .server_transpiler = {}, @@ -646,11 +646,10 @@ pub fn deinit(dev: *DevServer) void { .next_bundle = { var r = dev.next_bundle.requests.first; while (r) |request| { - defer dev.deferred_request_pool.put(request); // TODO: deinitializing in this state is almost certainly an assertion failure. // This code is shipped in release because it is only reachable by experimenntal server components. bun.debugAssert(request.data.handler != .server_handler); - request.data.deinit(); + defer request.data.deref(); r = request.next; } dev.next_bundle.route_queue.deinit(allocator); @@ -1089,6 +1088,8 @@ fn deferRequest( const method = bun.http.Method.which(req.method()) orelse .POST; deferred.data = .{ .route_bundle_index = route_bundle_index, + .dev = dev, + .ref_count = .init(), .handler = switch (kind) { .bundled_html_page => .{ .bundled_html_page = .{ .response = resp, .method = method } }, .server_handler => .{ @@ -1096,6 +1097,7 @@ fn deferRequest( }, }, }; + deferred.data.ref(); resp.onAborted(*DeferredRequest, DeferredRequest.onAbort, &deferred.data); requests_array.prepend(deferred); } @@ -1252,8 +1254,9 @@ fn onFrameworkRequestWithBundle( // routerTypeMain router_type.server_file_string.get() orelse str: { const name = dev.server_graph.bundled_files.keys()[fromOpaqueFileId(.server, router_type.server_file).get()]; - const str = try bun.String.createUTF8ForJS(dev.vm.global, dev.relativePath(name)); - dev.releaseRelativePathBuf(); + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + const str = try bun.String.createUTF8ForJS(dev.vm.global, dev.relativePath(relative_path_buf, name)); router_type.server_file_string = .create(str, dev.vm.global); break :str str; }, @@ -1269,14 +1272,21 @@ fn onFrameworkRequestWithBundle( } const arr = try JSValue.createEmptyArray(global, n); route = dev.router.routePtr(framework_bundle.route_index); - var route_name = bun.String.cloneUTF8(dev.relativePath(keys[fromOpaqueFileId(.server, route.file_page.unwrap().?).get()])); - try arr.putIndex(global, 0, route_name.transferToJS(global)); - dev.releaseRelativePathBuf(); + { + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + var route_name = bun.String.cloneUTF8(dev.relativePath(relative_path_buf, keys[fromOpaqueFileId(.server, route.file_page.unwrap().?).get()])); + try arr.putIndex(global, 0, route_name.transferToJS(global)); + } n = 1; while (true) { if (route.file_layout.unwrap()) |layout| { - var layout_name = bun.String.cloneUTF8(dev.relativePath(keys[fromOpaqueFileId(.server, layout).get()])); - defer dev.releaseRelativePathBuf(); + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + var layout_name = bun.String.cloneUTF8(dev.relativePath( + relative_path_buf, + keys[fromOpaqueFileId(.server, layout).get()], + )); try arr.putIndex(global, @intCast(n), layout_name.transferToJS(global)); n += 1; } @@ -1534,8 +1544,20 @@ pub const DeferredRequest = struct { pub const List = std.SinglyLinkedList(DeferredRequest); pub const Node = List.Node; + const RefCount = bun.ptr.RefCount(@This(), "ref_count", deinitImpl, .{}); + route_bundle_index: RouteBundle.Index, handler: Handler, + dev: *DevServer, + + /// This struct can have at most 2 references it: + /// - The dev server (`dev.current_bundle.requests`) + /// - uws.Response as a user data pointer + ref_count: RefCount, + + // expose `ref` and `deref` as public methods + pub const ref = RefCount.ref; + pub const deref = RefCount.deref; const Handler = union(enum) { /// For a .framework route. This says to call and render the page. @@ -1561,10 +1583,15 @@ pub const DeferredRequest = struct { assert(this.handler == .aborted); } + /// *WARNING*: Do not call this directly, instead call `.deref()` + /// /// Calling this is only required if the desired handler is going to be avoided, /// such as for bundling failures or aborting the server. /// Does not free the underlying `DeferredRequest.Node` - fn deinit(this: *DeferredRequest) void { + fn deinitImpl(this: *DeferredRequest) void { + bun.assert(this.ref_count.active_counts == 0); + + defer this.dev.deferred_request_pool.put(@fieldParentPtr("data", this)); switch (this.handler) { .server_handler => |*saved| saved.deinit(), .bundled_html_page, .aborted => {}, @@ -1573,17 +1600,18 @@ pub const DeferredRequest = struct { /// Deinitializes state by aborting the connection. fn abort(this: *DeferredRequest) void { - switch (this.handler) { + var handler = this.handler; + this.handler = .aborted; + switch (handler) { .server_handler => |*saved| { - saved.response.endWithoutBody(true); - saved.deinit(); + saved.ctx.onAbort(saved.response); + saved.js_request.deinit(); }, .bundled_html_page => |r| { r.response.endWithoutBody(true); }, - .aborted => return, + .aborted => {}, } - this.handler = .aborted; } }; @@ -1902,8 +1930,9 @@ fn makeArrayForServerComponentsPatch(dev: *DevServer, global: *jsc.JSGlobalObjec const arr = try jsc.JSArray.createEmpty(global, items.len); const names = dev.server_graph.bundled_files.keys(); for (items, 0..) |item, i| { - const str = bun.String.cloneUTF8(dev.relativePath(names[item.get()])); - defer dev.releaseRelativePathBuf(); + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + const str = bun.String.cloneUTF8(dev.relativePath(relative_path_buf, names[item.get()])); defer str.deref(); try arr.putIndex(global, @intCast(i), str.toJS(global)); } @@ -1998,8 +2027,8 @@ pub fn finalizeBundle( Output.debug("current_bundle.requests.first != null. this leaves pending requests without an error page!", .{}); } while (current_bundle.requests.popFirst()) |node| { - defer dev.deferred_request_pool.put(node); const req = &node.data; + defer req.deref(); req.abort(); } } @@ -2042,7 +2071,7 @@ pub fn finalizeBundle( .gts = undefined, }; - const quoted_source_contents: []const []const u8 = bv2.linker.graph.files.items(.quoted_source_contents); + const quoted_source_contents: []?[]u8 = bv2.linker.graph.files.items(.quoted_source_contents); // Pass 1, update the graph's nodes, resolving every bundler source // index into its `IncrementalGraph(...).FileIndex` for ( @@ -2055,7 +2084,7 @@ pub fn finalizeBundle( bun.assert(compile_result.javascript.result == .result); bun.assert(dev.server_transpiler.options.source_map != .none); bun.assert(!part_range.source_index.isRuntime()); - break :brk .empty; + break :brk .initEmpty(); }; // TODO: investigate why linker.files is not indexed by linker's index // const linker_index = bv2.linker.graph.stable_source_indices[index.get()]; @@ -2068,13 +2097,16 @@ pub fn finalizeBundle( }).receiveChunk( &ctx, index, - .{ .js = .{ - .code = compile_result.code(), - .source_map = .{ - .chunk = source_map, - .escaped_source = @constCast(quoted_contents), + .{ + .js = .{ + .code = compile_result.javascript.code(), + .code_allocator = compile_result.javascript.allocator(), + .source_map = .{ + .chunk = source_map, + .escaped_source = quoted_contents, + }, }, - } }, + }, graph == .ssr, ), } @@ -2160,6 +2192,7 @@ pub fn finalizeBundle( index, .{ .js = .{ .code = generated_js, + .code_allocator = dev.allocator, .source_map = null, } }, false, @@ -2552,8 +2585,8 @@ pub fn finalizeBundle( var inspector_agent = dev.inspector(); while (current_bundle.requests.popFirst()) |node| { - defer dev.deferred_request_pool.put(node); const req = &node.data; + defer req.deref(); const rb = dev.routeBundlePtr(req.route_bundle_index); rb.server_state = .possible_bundling_failures; @@ -2615,32 +2648,40 @@ pub fn finalizeBundle( ms_elapsed, }); - // Compute a file name to display - const file_name: ?[]const u8 = if (current_bundle.had_reload_event) - if (bv2.graph.entry_points.items.len > 0) - dev.relativePath( - bv2.graph.input_files.items(.source)[bv2.graph.entry_points.items[0].get()].path.text, - ) - else - null // TODO: How does this happen - else switch (dev.routeBundlePtr(current_bundle.requests.first.?.data.route_bundle_index).data) { - .html => |html| dev.relativePath(html.html_bundle.data.bundle.data.path), - .framework => |fw| file_name: { - const route = dev.router.routePtr(fw.route_index); - const opaque_id = route.file_page.unwrap() orelse - route.file_layout.unwrap() orelse - break :file_name null; - const server_index = fromOpaqueFileId(.server, opaque_id); - const abs_path = dev.server_graph.bundled_files.keys()[server_index.get()]; - break :file_name dev.relativePath(abs_path); - }, - }; - defer dev.releaseRelativePathBuf(); - const total_count = bv2.graph.entry_points.items.len; - if (file_name) |name| { - Output.prettyError(": {s}", .{name}); - if (total_count > 1) { - Output.prettyError(" + {d} more", .{total_count - 1}); + // Intentionally creating a new scope here so we can limit the lifetime + // of the `relative_path_buf` + { + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + + // Compute a file name to display + const file_name: ?[]const u8 = if (current_bundle.had_reload_event) + if (bv2.graph.entry_points.items.len > 0) + dev.relativePath( + relative_path_buf, + bv2.graph.input_files.items(.source)[bv2.graph.entry_points.items[0].get()].path.text, + ) + else + null // TODO: How does this happen + else switch (dev.routeBundlePtr(current_bundle.requests.first.?.data.route_bundle_index).data) { + .html => |html| dev.relativePath(relative_path_buf, html.html_bundle.data.bundle.data.path), + .framework => |fw| file_name: { + const route = dev.router.routePtr(fw.route_index); + const opaque_id = route.file_page.unwrap() orelse + route.file_layout.unwrap() orelse + break :file_name null; + const server_index = fromOpaqueFileId(.server, opaque_id); + const abs_path = dev.server_graph.bundled_files.keys()[server_index.get()]; + break :file_name dev.relativePath(relative_path_buf, abs_path); + }, + }; + + const total_count = bv2.graph.entry_points.items.len; + if (file_name) |name| { + Output.prettyError(": {s}", .{name}); + if (total_count > 1) { + Output.prettyError(" + {d} more", .{total_count - 1}); + } } } Output.prettyError("\n", .{}); @@ -2656,8 +2697,8 @@ pub fn finalizeBundle( defer dev.graph_safety_lock.lock(); while (current_bundle.requests.popFirst()) |node| { - defer dev.deferred_request_pool.put(node); const req = &node.data; + defer req.deref(); const rb = dev.routeBundlePtr(req.route_bundle_index); rb.server_state = .loaded; @@ -2999,6 +3040,9 @@ fn sendBuiltInNotFound(resp: anytype) void { } fn printMemoryLine(dev: *DevServer) void { + if (comptime !bun.Environment.enableAllocScopes) { + return; + } if (!debug.isVisible()) return; Output.prettyErrorln("DevServer tracked {}, measured: {} ({}), process: {}", .{ bun.fmt.size(dev.memoryCost(), .{}), @@ -3339,8 +3383,9 @@ pub fn writeVisualizerMessage(dev: *DevServer, payload: *std.ArrayList(u8)) !voi g.bundled_files.values(), 0.., ) |k, v, i| { - const normalized_key = dev.relativePath(k); - defer dev.releaseRelativePathBuf(); + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + const normalized_key = dev.relativePath(relative_path_buf, k); try w.writeInt(u32, @intCast(normalized_key.len), .little); if (k.len == 0) continue; try w.writeAll(normalized_key); @@ -3776,12 +3821,12 @@ pub fn onRouterCollisionError(dev: *DevServer, rel_path: []const u8, other_id: O }, }); Output.prettyErrorln(" - {s}", .{rel_path}); + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); Output.prettyErrorln(" - {s}", .{ - dev.relativePath(dev.server_graph.bundled_files.keys()[fromOpaqueFileId(.server, other_id).get()]), + dev.relativePath(relative_path_buf, dev.server_graph.bundled_files.keys()[fromOpaqueFileId(.server, other_id).get()]), }); Output.flush(); - - dev.releaseRelativePathBuf(); } fn toOpaqueFileId(comptime side: bake.Side, index: IncrementalGraph(side).FileIndex) OpaqueFileId { @@ -3806,8 +3851,15 @@ fn fromOpaqueFileId(comptime side: bake.Side, id: OpaqueFileId) IncrementalGraph /// Returns posix style path, suitible for URLs and reproducible hashes. /// To avoid overwriting memory, this has a lock for the buffer. -pub fn relativePath(dev: *DevServer, path: []const u8) []const u8 { - dev.relative_path_buf_lock.lock(); +/// +/// +/// You must pass the pathbuffer contained within `dev.relative_path_buffer`! +pub fn relativePath(dev: *DevServer, relative_path_buf: *bun.PathBuffer, path: []const u8) []const u8 { + // You must pass the pathbuffer contained within `dev.relative_path_buffer`! + bun.assert_eql( + @intFromPtr(relative_path_buf), + @intFromPtr(&dev.relative_path_buf.unsynchronized_value), + ); bun.assert(dev.root[dev.root.len - 1] != '/'); if (!std.fs.path.isAbsolute(path)) { @@ -3821,19 +3873,12 @@ pub fn relativePath(dev: *DevServer, path: []const u8) []const u8 { return path[dev.root.len + 1 ..]; } - const rel = bun.path.relativePlatformBuf(&dev.relative_path_buf, dev.root, path, .auto, true); + const rel = bun.path.relativePlatformBuf(relative_path_buf, dev.root, path, .auto, true); // @constCast: `rel` is owned by a buffer on `dev`, which is mutable bun.path.platformToPosixInPlace(u8, @constCast(rel)); return rel; } -pub fn releaseRelativePathBuf(dev: *DevServer) void { - dev.relative_path_buf_lock.unlock(); - if (bun.Environment.isDebug) { - dev.relative_path_buf = undefined; - } -} - /// Either of two conditions make this true: /// - The inspector is enabled /// - The user passed "console": true in serve({development: {console: true}}) options @@ -4004,7 +4049,7 @@ pub fn onPluginsResolved(dev: *DevServer, plugins: ?*Plugin) !void { pub fn onPluginsRejected(dev: *DevServer) !void { dev.plugin_state = .err; while (dev.next_bundle.requests.popFirst()) |item| { - defer dev.deferred_request_pool.put(item); + defer item.data.deref(); item.data.abort(); } dev.next_bundle.route_queue.clearRetainingCapacity(); @@ -4084,6 +4129,7 @@ const SourceMap = bun.sourcemap; const Watcher = bun.Watcher; const assert = bun.assert; const bake = bun.bake; +const DebugGuardedValue = bun.threading.DebugGuardedValue; const DynamicBitSetUnmanaged = bun.bit_set.DynamicBitSetUnmanaged; const Log = bun.logger.Log; const MimeType = bun.http.MimeType; diff --git a/src/bake/DevServer/ErrorReportRequest.zig b/src/bake/DevServer/ErrorReportRequest.zig index a23443f789..a71bfdce6d 100644 --- a/src/bake/DevServer/ErrorReportRequest.zig +++ b/src/bake/DevServer/ErrorReportRequest.zig @@ -147,11 +147,12 @@ pub fn runWithBody(ctx: *ErrorReportRequest, body: []const u8, r: AnyResponse) ! if (index >= 1 and (index - 1) < result.file_paths.len) { const abs_path = result.file_paths[@intCast(index - 1)]; frame.source_url = .init(abs_path); - const rel_path = ctx.dev.relativePath(abs_path); - defer ctx.dev.releaseRelativePathBuf(); + const relative_path_buf = ctx.dev.relative_path_buf.lock(); + const rel_path = ctx.dev.relativePath(relative_path_buf, abs_path); if (bun.strings.eql(frame.function_name.value.ZigString.slice(), rel_path)) { frame.function_name = .empty; } + ctx.dev.relative_path_buf.unlock(); frame.remapped = true; if (runtime_lines == null) { @@ -240,8 +241,8 @@ pub fn runWithBody(ctx: *ErrorReportRequest, body: []const u8, r: AnyResponse) ! const src_to_write = frame.source_url.value.ZigString.slice(); if (bun.strings.hasPrefixComptime(src_to_write, "/")) { - const file = ctx.dev.relativePath(src_to_write); - defer ctx.dev.releaseRelativePathBuf(); + const relative_path_buf = ctx.dev.relative_path_buf.lock(); + const file = ctx.dev.relativePath(relative_path_buf, src_to_write); try w.writeInt(u32, @intCast(file.len), .little); try w.writeAll(file); } else { diff --git a/src/bake/DevServer/IncrementalGraph.zig b/src/bake/DevServer/IncrementalGraph.zig index 95d4bff854..96228cad69 100644 --- a/src/bake/DevServer/IncrementalGraph.zig +++ b/src/bake/DevServer/IncrementalGraph.zig @@ -134,12 +134,15 @@ pub fn IncrementalGraph(side: bake.Side) type { .client => struct { /// Content depends on `flags.kind` /// See function wrappers to safely read into this data - content: extern union { - /// Allocated by `dev.allocator`. Access with `.jsCode()` + content: union { + /// Access contents with `.jsCode()`. /// When stale, the code is "", otherwise it contains at /// least one non-whitespace character, as empty chunks /// contain at least a function wrapper. - js_code_ptr: [*]const u8, + js_code: struct { + ptr: [*]const u8, + allocator: std.mem.Allocator, + }, /// Access with `.cssAssetId()` css_asset_id: u64, @@ -187,18 +190,20 @@ pub fn IncrementalGraph(side: bake.Side) type { }; comptime { - const d = std.debug; - if (!Environment.isDebug) { - d.assert(@sizeOf(@This()) == @sizeOf(u64) * 3); - d.assert(@alignOf(@This()) == @alignOf([*]u8)); + if (@import("builtin").mode == .ReleaseFast or @import("builtin").mode == .ReleaseSmall) { + bun.assert_eql(@sizeOf(@This()), @sizeOf(u64) * 5); + bun.assert_eql(@alignOf(@This()), @alignOf([*]u8)); } } - fn initJavaScript(code_slice: []const u8, flags: Flags, source_map: PackedMap.RefOrEmpty) @This() { + fn initJavaScript(code_slice: []const u8, code_allocator: std.mem.Allocator, flags: Flags, source_map: PackedMap.RefOrEmpty) @This() { assert(flags.kind == .js or flags.kind == .asset); assert(flags.source_map_state == std.meta.activeTag(source_map)); return .{ - .content = .{ .js_code_ptr = code_slice.ptr }, + .content = .{ .js_code = .{ + .ptr = code_slice.ptr, + .allocator = code_allocator, + } }, .code_len = @intCast(code_slice.len), .flags = flags, .source_map = source_map.untag(), @@ -228,7 +233,12 @@ pub fn IncrementalGraph(side: bake.Side) type { fn jsCode(file: @This()) []const u8 { assert(file.flags.kind.hasInlinejscodeChunk()); - return file.content.js_code_ptr[0..file.code_len]; + return file.content.js_code.ptr[0..file.code_len]; + } + + fn freeJsCode(file: *@This()) void { + assert(file.flags.kind.hasInlinejscodeChunk()); + file.content.js_code.allocator.free(file.jsCode()); } fn cssAssetId(file: @This()) u64 { @@ -258,7 +268,7 @@ pub fn IncrementalGraph(side: bake.Side) type { fn freeFileContent(g: *IncrementalGraph(.client), key: []const u8, file: *File, css: enum { unref_css, ignore_css }) void { switch (file.flags.kind) { .js, .asset => { - g.owner().allocator.free(file.jsCode()); + file.freeJsCode(); switch (file.sourceMap()) { .ref => |ptr| { ptr.derefWithContext(g.owner()); @@ -409,9 +419,10 @@ pub fn IncrementalGraph(side: bake.Side) type { content: union(enum) { js: struct { code: []const u8, + code_allocator: std.mem.Allocator, source_map: ?struct { chunk: SourceMap.Chunk, - escaped_source: []u8, + escaped_source: ?[]u8, }, }, css: u64, @@ -498,24 +509,22 @@ pub fn IncrementalGraph(side: bake.Side) type { switch (content) { .css => |css| gop.value_ptr.* = .initCSS(css, flags), .js => |js| { - dev.allocation_scope.assertOwned(js.code); - // Insert new source map or patch existing empty source map. const source_map: PackedMap.RefOrEmpty = brk: { if (js.source_map) |source_map| { bun.debugAssert(!flags.is_html_route); // suspect behind #17956 if (source_map.chunk.buffer.len() > 0) { - dev.allocation_scope.assertOwned(source_map.chunk.buffer.list.items); - dev.allocation_scope.assertOwned(source_map.escaped_source); flags.source_map_state = .ref; break :brk .{ .ref = PackedMap.newNonEmpty( source_map.chunk, - source_map.escaped_source, + source_map.escaped_source.?, ) }; } var take = source_map.chunk.buffer; take.deinit(); - dev.allocator.free(source_map.escaped_source); + if (source_map.escaped_source) |escaped_source| { + bun.default_allocator.free(escaped_source); + } } // Must precompute this. Otherwise, source maps won't have @@ -531,7 +540,7 @@ pub fn IncrementalGraph(side: bake.Side) type { } }; }; - gop.value_ptr.* = .initJavaScript(js.code, flags, source_map); + gop.value_ptr.* = .initJavaScript(js.code, js.code_allocator, flags, source_map); // Track JavaScript chunks for concatenation try g.current_chunk_parts.append(dev.allocator, file_index); @@ -603,14 +612,26 @@ pub fn IncrementalGraph(side: bake.Side) type { // Track the file index for this chunk try g.current_chunk_file_indices.append(dev.allocator, file_index); - // Store the source map instead of freeing it - if (content.js.source_map) |source_map| { - const packed_map = PackedMap.newNonEmpty(source_map.chunk, source_map.escaped_source); - try g.current_chunk_source_maps.append(dev.allocator, .{ - .ref = packed_map, - }); + // TODO: we probably want to store SSR chunks but not + // server chunks, but not 100% sure + const should_immediately_free_sourcemap = false; + if (should_immediately_free_sourcemap) { + if (content.js.source_map) |source_map| { + var take = source_map.chunk.buffer; + take.deinit(); + if (source_map.escaped_source) |escaped_source| { + bun.default_allocator.free(escaped_source); + } + } } else { - try g.current_chunk_source_maps.append(dev.allocator, PackedMap.RefOrEmpty.blank_empty); + if (content.js.source_map) |source_map| { + const packed_map = PackedMap.newNonEmpty(source_map.chunk, source_map.escaped_source); + try g.current_chunk_source_maps.append(dev.allocator, .{ + .ref = packed_map, + }); + } else { + try g.current_chunk_source_maps.append(dev.allocator, PackedMap.RefOrEmpty.blank_empty); + } } } }, @@ -695,6 +716,14 @@ pub fn IncrementalGraph(side: bake.Side) type { .css => try g.processCSSChunkImportRecords(ctx, temp_alloc, &quick_lookup, &new_imports, file_index, bundle_graph_index), } + // We need to add this here to not trip up + // `checkEdgeRemoval(edge_idx)` (which checks that there no + // references to `edge_idx`. + // + // I don't think `g.first_import.items[file_index]` is ever read + // from again in this function, so this is safe. + g.first_import.items[file_index.get()] = .none; + // '.seen = false' means an import was removed and should be freed for (quick_lookup.values()[0..quick_lookup_values_to_care_len]) |val| { if (!val.seen) { @@ -718,6 +747,12 @@ pub fn IncrementalGraph(side: bake.Side) type { } } + /// When we delete an edge, we need to delete it by connecting the + /// previous dependency (importer) edge to the next depedenency + /// (importer) edge. + /// + /// DO NOT ONLY CALL THIS FUNCTION TO TRY TO DELETE AN EDGE, YOU MUST DELETE + /// THE IMPORTS TOO! fn disconnectEdgeFromDependencyList(g: *@This(), edge_index: EdgeIndex) void { const edge = &g.edges.items[edge_index.get()]; const imported = edge.imported.get(); @@ -1418,13 +1453,18 @@ pub fn IncrementalGraph(side: bake.Side) type { // TODO: DevServer should get a stdio manager which can process // the error list as it changes while also supporting a REPL log.print(Output.errorWriter()) catch {}; - const failure = try SerializedFailure.initFromLog( - dev, - fail_owner, - dev.relativePath(gop.key_ptr.*), - log.msgs.items, - ); - defer dev.releaseRelativePathBuf(); + const failure = failure: { + const relative_path_buf = dev.relative_path_buf.lock(); + defer dev.relative_path_buf.unlock(); + // this string is just going to be memcpy'd into the log buffer + const owner_display_name = dev.relativePath(relative_path_buf, gop.key_ptr.*); + break :failure try SerializedFailure.initFromLog( + dev, + fail_owner, + owner_display_name, + log.msgs.items, + ); + }; const fail_gop = try dev.bundling_failures.getOrPut(dev.allocator, failure); try dev.incremental_result.failures_added.append(dev.allocator, failure); if (fail_gop.found_existing) { @@ -1440,6 +1480,7 @@ pub fn IncrementalGraph(side: bake.Side) type { // Disconnect all imports var it: ?EdgeIndex = g.first_import.items[index.get()].unwrap(); + g.first_import.items[index.get()] = .none; while (it) |edge_index| { const dep = g.edges.items[edge_index.get()]; it = dep.next_import.unwrap(); @@ -1643,13 +1684,14 @@ pub fn IncrementalGraph(side: bake.Side) type { try w.writeAll("}, {\n main: "); const initial_response_entry_point = options.initial_response_entry_point; if (initial_response_entry_point.len > 0) { + const relative_path_buf = g.owner().relative_path_buf.lock(); + defer g.owner().relative_path_buf.unlock(); try bun.js_printer.writeJSONString( - g.owner().relativePath(initial_response_entry_point), + g.owner().relativePath(relative_path_buf, initial_response_entry_point), @TypeOf(w), w, .utf8, ); - g.owner().releaseRelativePathBuf(); } else { try w.writeAll("null"); } @@ -1668,13 +1710,14 @@ pub fn IncrementalGraph(side: bake.Side) type { if (options.react_refresh_entry_point.len > 0) { try w.writeAll(",\n refresh: "); + const relative_path_buf = g.owner().relative_path_buf.lock(); + defer g.owner().relative_path_buf.unlock(); try bun.js_printer.writeJSONString( - g.owner().relativePath(options.react_refresh_entry_point), + g.owner().relativePath(relative_path_buf, options.react_refresh_entry_point), @TypeOf(w), w, .utf8, ); - g.owner().releaseRelativePathBuf(); } try w.writeAll("\n})"); }, @@ -1743,13 +1786,8 @@ pub fn IncrementalGraph(side: bake.Side) type { .client => { const files = g.bundled_files.values(); - // This buffer is temporary, holding the quoted source paths, joined with commas. - var source_map_strings = std.ArrayList(u8).init(arena); - defer source_map_strings.deinit(); - - const dev = g.owner(); - dev.relative_path_buf_lock.lock(); - defer dev.relative_path_buf_lock.unlock(); + const buf = bun.path_buffer_pool.get(); + defer bun.path_buffer_pool.put(buf); const buf = bun.path_buffer_pool.get(); defer bun.path_buffer_pool.put(buf); @@ -1816,6 +1854,7 @@ pub fn IncrementalGraph(side: bake.Side) type { // Disconnect all imports { var it: ?EdgeIndex = g.first_import.items[file_index.get()].unwrap(); + g.first_import.items[file_index.get()] = .none; while (it) |edge_index| { const dep = g.edges.items[edge_index.get()]; it = dep.next_import.unwrap(); @@ -1858,6 +1897,8 @@ pub fn IncrementalGraph(side: bake.Side) type { /// Does nothing besides release the `Edge` for reallocation by `newEdge` /// Caller must detach the dependency from the linked list it is in. fn freeEdge(g: *@This(), edge_index: EdgeIndex) void { + igLog("IncrementalGraph(0x{x}, {s}).freeEdge({d})", .{ @intFromPtr(g), @tagName(side), edge_index.get() }); + defer g.checkEdgeRemoval(edge_index); if (Environment.isDebug) { g.edges.items[edge_index.get()] = undefined; } @@ -1872,6 +1913,49 @@ pub fn IncrementalGraph(side: bake.Side) type { } } + /// It is very easy to call `g.freeEdge(idx)` but still keep references + /// to the idx around, basically causing use-after-free with more steps + /// and no asan to check it since we are dealing with indices and not + /// pointers to memory. + /// + /// So we'll check it manually by making sure there are no references to + /// `edge_index` in the graph. + fn checkEdgeRemoval(g: *@This(), edge_index: EdgeIndex) void { + // Enable this on any builds with asan enabled so we can catch stuff + // in CI too + const enabled = bun.asan.enabled or bun.Environment.ci_assert; + if (comptime !enabled) return; + + for (g.first_dep.items) |maybe_first_dep| { + if (maybe_first_dep.unwrap()) |first_dep| { + bun.assert_neql(first_dep.get(), edge_index.get()); + } + } + + for (g.first_import.items) |maybe_first_import| { + if (maybe_first_import.unwrap()) |first_import| { + bun.assert_neql(first_import.get(), edge_index.get()); + } + } + + for (g.edges.items) |edge| { + const in_free_list = in_free_list: { + for (g.edges_free_list.items) |free_edge_index| { + if (free_edge_index.get() == edge_index.get()) { + break :in_free_list true; + } + } + break :in_free_list false; + }; + + if (in_free_list) continue; + + bun.assert_neql(edge.prev_dependency.unwrapGet(), edge_index.get()); + bun.assert_neql(edge.next_import.unwrapGet(), edge_index.get()); + bun.assert_neql(edge.next_dependency.unwrapGet(), edge_index.get()); + } + } + pub fn owner(g: *@This()) *DevServer { return @alignCast(@fieldParentPtr(@tagName(side) ++ "_graph", g)); } diff --git a/src/bake/DevServer/PackedMap.zig b/src/bake/DevServer/PackedMap.zig index 7a2d2f840a..83fb0922e7 100644 --- a/src/bake/DevServer/PackedMap.zig +++ b/src/bake/DevServer/PackedMap.zig @@ -11,6 +11,7 @@ ref_count: RefCount, /// This is stored to allow lazy construction of source map files. vlq_ptr: [*]u8, vlq_len: u32, +vlq_allocator: std.mem.Allocator, /// The bundler runs quoting on multiple threads, so it only makes /// sense to preserve that effort for concatenation and /// re-concatenation. @@ -31,24 +32,26 @@ end_state: struct { /// already counted for. bits_used_for_memory_cost_dedupe: u32 = 0, -pub fn newNonEmpty(source_map: SourceMap.Chunk, quoted_contents: []u8) bun.ptr.RefPtr(PackedMap) { - assert(source_map.buffer.list.items.len > 0); +pub fn newNonEmpty(chunk: SourceMap.Chunk, quoted_contents: []u8) bun.ptr.RefPtr(PackedMap) { + assert(chunk.buffer.list.items.len > 0); + var buffer = chunk.buffer; + const slice = buffer.toOwnedSlice(); return .new(.{ .ref_count = .init(), - .vlq_ptr = source_map.buffer.list.items.ptr, - .vlq_len = @intCast(source_map.buffer.list.items.len), + .vlq_ptr = slice.ptr, + .vlq_len = @intCast(slice.len), + .vlq_allocator = buffer.allocator, .quoted_contents_ptr = quoted_contents.ptr, .quoted_contents_len = @intCast(quoted_contents.len), .end_state = .{ - .original_line = source_map.end_state.original_line, - .original_column = source_map.end_state.original_column, + .original_line = chunk.end_state.original_line, + .original_column = chunk.end_state.original_column, }, }); } -fn destroy(self: *@This(), dev: *DevServer) void { - dev.allocator.free(self.vlq()); - dev.allocator.free(self.quotedContents()); +fn destroy(self: *@This(), _: *DevServer) void { + self.vlq_allocator.free(self.vlq()); bun.destroy(self); } @@ -78,7 +81,7 @@ pub fn quotedContents(self: *const @This()) []u8 { comptime { if (!Environment.isDebug) { - assert_eql(@sizeOf(@This()), @sizeOf(usize) * 5); + assert_eql(@sizeOf(@This()), @sizeOf(usize) * 7); assert_eql(@alignOf(@This()), @alignOf(usize)); } } @@ -156,6 +159,8 @@ pub const RefOrEmpty = union(enum(u1)) { }; }; +const std = @import("std"); + const bun = @import("bun"); const Environment = bun.Environment; const SourceMap = bun.sourcemap; diff --git a/src/bake/DevServer/SourceMapStore.zig b/src/bake/DevServer/SourceMapStore.zig index 32229688dd..b4905cd0aa 100644 --- a/src/bake/DevServer/SourceMapStore.zig +++ b/src/bake/DevServer/SourceMapStore.zig @@ -93,9 +93,6 @@ pub const Entry = struct { var source_map_strings = std.ArrayList(u8).init(arena); defer source_map_strings.deinit(); - dev.relative_path_buf_lock.lock(); - defer dev.relative_path_buf_lock.unlock(); - const buf = bun.path_buffer_pool.get(); defer bun.path_buffer_pool.put(buf); diff --git a/src/bake/DevServer/memory_cost.zig b/src/bake/DevServer/memory_cost.zig index 17516b050e..b574e9427c 100644 --- a/src/bake/DevServer/memory_cost.zig +++ b/src/bake/DevServer/memory_cost.zig @@ -45,7 +45,6 @@ pub fn memoryCostDetailed(dev: *DevServer) MemoryCost { .magic = {}, .memory_visualizer_timer = {}, .plugin_state = {}, - .relative_path_buf_lock = {}, .server_register_update_callback = {}, .server_fetch_function_callback = {}, .watcher_atomics = {}, diff --git a/src/bun.js.zig b/src/bun.js.zig index d05a6818ea..3def2c2445 100644 --- a/src/bun.js.zig +++ b/src/bun.js.zig @@ -23,7 +23,7 @@ pub const Run = struct { js_ast.Expr.Data.Store.create(); js_ast.Stmt.Data.Store.create(); - var arena = try Arena.init(); + const arena = try Arena.init(); if (!ctx.debug.loaded_bunfig) { try bun.cli.Arguments.loadConfigPath(ctx.allocator, true, "bunfig.toml", ctx, .RunCommand); @@ -31,7 +31,7 @@ pub const Run = struct { run = .{ .vm = try VirtualMachine.initWithModuleGraph(.{ - .allocator = arena.allocator(), + .allocator = bun.default_allocator, .log = ctx.log, .args = ctx.args, .graph = graph_ptr, @@ -48,7 +48,7 @@ pub const Run = struct { vm.preload = ctx.preloads; vm.argv = ctx.passthrough; vm.arena = &run.arena; - vm.allocator = arena.allocator(); + vm.allocator = bun.default_allocator; b.options.install = ctx.install; b.resolver.opts.install = ctx.install; @@ -160,12 +160,12 @@ pub const Run = struct { js_ast.Expr.Data.Store.create(); js_ast.Stmt.Data.Store.create(); - var arena = try Arena.init(); + const arena = try Arena.init(); run = .{ .vm = try VirtualMachine.init( .{ - .allocator = arena.allocator(), + .allocator = bun.default_allocator, .log = ctx.log, .args = ctx.args, .store_fd = ctx.debug.hot_reload != .none, @@ -187,7 +187,7 @@ pub const Run = struct { vm.preload = ctx.preloads; vm.argv = ctx.passthrough; vm.arena = &run.arena; - vm.allocator = arena.allocator(); + vm.allocator = bun.default_allocator; if (ctx.runtime_options.eval.script.len > 0) { const script_source = try bun.default_allocator.create(logger.Source); diff --git a/src/bun.js/SavedSourceMap.zig b/src/bun.js/SavedSourceMap.zig index 86bd34fe9c..cbff1a8804 100644 --- a/src/bun.js/SavedSourceMap.zig +++ b/src/bun.js/SavedSourceMap.zig @@ -171,7 +171,7 @@ pub fn deinit(this: *SavedSourceMap) void { } pub fn putMappings(this: *SavedSourceMap, source: *const logger.Source, mappings: MutableString) !void { - try this.putValue(source.path.text, Value.init(bun.cast(*SavedMappings, mappings.list.items.ptr))); + try this.putValue(source.path.text, Value.init(bun.cast(*SavedMappings, try bun.default_allocator.dupe(u8, mappings.list.items)))); } pub fn putValue(this: *SavedSourceMap, path: []const u8, value: Value) !void { diff --git a/src/bun.js/VirtualMachine.zig b/src/bun.js/VirtualMachine.zig index 67bf251a07..0525e201fc 100644 --- a/src/bun.js/VirtualMachine.zig +++ b/src/bun.js/VirtualMachine.zig @@ -194,6 +194,8 @@ commonjs_custom_extensions: bun.StringArrayHashMapUnmanaged(node_module_module.C /// The value is decremented when defaults are restored. has_mutated_built_in_extensions: u32 = 0, +initial_script_execution_context_identifier: i32, + pub const ProcessAutoKiller = @import("./ProcessAutoKiller.zig"); pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSGlobalObject, JSValue) void; @@ -367,7 +369,7 @@ const SourceMapHandlerGetter = struct { pub fn onChunk(this: *SourceMapHandlerGetter, chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void { var temp_json_buffer = bun.MutableString.initEmpty(bun.default_allocator); defer temp_json_buffer.deinit(); - temp_json_buffer = try chunk.printSourceMapContentsAtOffset(source, temp_json_buffer, true, SavedSourceMap.vlq_offset, true); + try chunk.printSourceMapContentsAtOffset(source, &temp_json_buffer, true, SavedSourceMap.vlq_offset, true); const source_map_url_prefix_start = "//# sourceMappingURL=data:application/json;base64,"; // TODO: do we need to %-encode the path? const source_url_len = source.path.text.len; @@ -984,6 +986,7 @@ pub fn initWithModuleGraph( .standalone_module_graph = opts.graph.?, .debug_thread_id = if (Environment.allow_assert) std.Thread.getCurrentId(), .destruct_main_thread_on_exit = opts.destruct_main_thread_on_exit, + .initial_script_execution_context_identifier = if (opts.is_main_thread) 1 else std.math.maxInt(i32), }; vm.source_mappings.init(&vm.saved_source_map_table); vm.regular_event_loop.tasks = EventLoop.Queue.init( @@ -1016,7 +1019,7 @@ pub fn initWithModuleGraph( vm.global = JSGlobalObject.create( vm, vm.console, - if (opts.is_main_thread) 1 else std.math.maxInt(i32), + vm.initial_script_execution_context_identifier, false, false, null, @@ -1105,6 +1108,7 @@ pub fn init(opts: Options) !*VirtualMachine { .ref_strings_mutex = .{}, .debug_thread_id = if (Environment.allow_assert) std.Thread.getCurrentId(), .destruct_main_thread_on_exit = opts.destruct_main_thread_on_exit, + .initial_script_execution_context_identifier = if (opts.is_main_thread) 1 else std.math.maxInt(i32), }; vm.source_mappings.init(&vm.saved_source_map_table); vm.regular_event_loop.tasks = EventLoop.Queue.init( @@ -1134,7 +1138,7 @@ pub fn init(opts: Options) !*VirtualMachine { vm.global = JSGlobalObject.create( vm, vm.console, - if (opts.is_main_thread) 1 else std.math.maxInt(i32), + vm.initial_script_execution_context_identifier, opts.smol, opts.eval, null, @@ -1264,6 +1268,7 @@ pub fn initWorker( .debug_thread_id = if (Environment.allow_assert) std.Thread.getCurrentId(), // This option is irrelevant for Workers .destruct_main_thread_on_exit = false, + .initial_script_execution_context_identifier = @as(i32, @intCast(worker.execution_context_id)), }; vm.source_mappings.init(&vm.saved_source_map_table); vm.regular_event_loop.tasks = EventLoop.Queue.init( @@ -1297,7 +1302,7 @@ pub fn initWorker( vm.global = JSGlobalObject.create( vm, vm.console, - @as(i32, @intCast(worker.execution_context_id)), + vm.initial_script_execution_context_identifier, worker.mini, opts.eval, worker.cpp_worker, @@ -1355,6 +1360,7 @@ pub fn initBake(opts: Options) anyerror!*VirtualMachine { .ref_strings_mutex = .{}, .debug_thread_id = if (Environment.allow_assert) std.Thread.getCurrentId(), .destruct_main_thread_on_exit = opts.destruct_main_thread_on_exit, + .initial_script_execution_context_identifier = if (opts.is_main_thread) 1 else std.math.maxInt(i32), }; vm.source_mappings.init(&vm.saved_source_map_table); vm.regular_event_loop.tasks = EventLoop.Queue.init( diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 25a4c52774..62713db2a3 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -1306,6 +1306,15 @@ pub fn getS3DefaultClient(globalThis: *jsc.JSGlobalObject, _: *jsc.JSObject) jsc return globalThis.bunVM().rareData().s3DefaultClient(globalThis); } +pub fn getTLSDefaultCiphers(globalThis: *jsc.JSGlobalObject, _: *jsc.JSObject) jsc.JSValue { + return globalThis.bunVM().rareData().tlsDefaultCiphers(); +} + +pub fn setTLSDefaultCiphers(globalThis: *jsc.JSGlobalObject, _: *jsc.JSObject, ciphers: jsc.JSValue) jsc.JSValue { + globalThis.bunVM().rareData().setTLSDefaultCiphers(ciphers); + return .js_undefined; +} + pub fn getValkeyDefaultClient(globalThis: *jsc.JSGlobalObject, _: *jsc.JSObject) jsc.JSValue { const valkey = jsc.API.Valkey.create(globalThis, &.{.js_undefined}) catch |err| { if (err != error.JSError) { diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 93151d186a..73e956c104 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -325,7 +325,7 @@ fn transformOptionsFromJSC(globalObject: *jsc.JSGlobalObject, temp_allocator: st try external.toZigString(&zig_str, globalThis); if (zig_str.len == 0) break :external; var single_external = allocator.alloc(string, 1) catch unreachable; - single_external[0] = std.fmt.allocPrint(allocator, "{}", .{external}) catch unreachable; + single_external[0] = std.fmt.allocPrint(allocator, "{}", .{zig_str}) catch unreachable; transpiler.transform.external = single_external; } else if (toplevel_type.isArray()) { const count = try external.getLength(globalThis); @@ -342,7 +342,7 @@ fn transformOptionsFromJSC(globalObject: *jsc.JSGlobalObject, temp_allocator: st var zig_str = jsc.ZigString.init(""); try entry.toZigString(&zig_str, globalThis); if (zig_str.len == 0) continue; - externals[i] = std.fmt.allocPrint(allocator, "{}", .{external}) catch unreachable; + externals[i] = std.fmt.allocPrint(allocator, "{}", .{zig_str}) catch unreachable; i += 1; } diff --git a/src/bun.js/api/Timer/WTFTimer.zig b/src/bun.js/api/Timer/WTFTimer.zig index e91d0d321e..e93883d760 100644 --- a/src/bun.js/api/Timer/WTFTimer.zig +++ b/src/bun.js/api/Timer/WTFTimer.zig @@ -14,6 +14,7 @@ event_loop_timer: EventLoopTimer, imminent: *std.atomic.Value(?*WTFTimer), repeat: bool, lock: bun.Mutex = .{}, +script_execution_context_id: bun.webcore.ScriptExecutionContext.Identifier, const new = bun.TrivialNew(WTFTimer); @@ -56,9 +57,13 @@ pub fn update(this: *WTFTimer, seconds: f64, repeat: bool) void { pub fn cancel(this: *WTFTimer) void { this.lock.lock(); defer this.lock.unlock(); - this.imminent.store(null, .seq_cst); - if (this.event_loop_timer.state == .ACTIVE) { - this.vm.timer.remove(&this.event_loop_timer); + + if (this.script_execution_context_id.valid()) { + this.imminent.store(null, .seq_cst); + + if (this.event_loop_timer.state == .ACTIVE) { + this.vm.timer.remove(&this.event_loop_timer); + } } } @@ -97,6 +102,7 @@ export fn WTFTimer__create(run_loop_timer: *RunLoopTimer) ?*anyopaque { }, .run_loop_timer = run_loop_timer, .repeat = false, + .script_execution_context_id = @enumFromInt(vm.initial_script_execution_context_identifier), }); return this; diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index 1be8c8afee..54acac087b 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -503,36 +503,15 @@ pub fn jsGetPackedSettings(globalObject: *jsc.JSGlobalObject, callframe: *jsc.Ca } const Handlers = struct { - onError: jsc.JSValue = .zero, - onWrite: jsc.JSValue = .zero, - onStreamError: jsc.JSValue = .zero, - onStreamStart: jsc.JSValue = .zero, - onStreamHeaders: jsc.JSValue = .zero, - onStreamEnd: jsc.JSValue = .zero, - onStreamData: jsc.JSValue = .zero, - onRemoteSettings: jsc.JSValue = .zero, - onLocalSettings: jsc.JSValue = .zero, - onWantTrailers: jsc.JSValue = .zero, - onPing: jsc.JSValue = .zero, - onEnd: jsc.JSValue = .zero, - onGoAway: jsc.JSValue = .zero, - onAborted: jsc.JSValue = .zero, - onAltSvc: jsc.JSValue = .zero, - onOrigin: jsc.JSValue = .zero, - onFrameError: jsc.JSValue = .zero, // Added for frameError events binary_type: BinaryType = .Buffer, vm: *jsc.VirtualMachine, globalObject: *jsc.JSGlobalObject, - strong_ctx: jsc.Strong.Optional = .empty, - pub fn callEventHandler(this: *Handlers, comptime event: @Type(.enum_literal), thisValue: JSValue, data: []const JSValue) bool { - const callback = @field(this, @tagName(event)); - if (callback == .zero) { - return false; - } + pub fn callEventHandler(this: *Handlers, comptime event: H2FrameParser.js.gc, thisValue: JSValue, context: jsc.JSValue, data: []const JSValue) bool { + const callback = event.get(thisValue) orelse return false; - this.vm.eventLoop().runCallback(callback, this.globalObject, thisValue, data); + this.vm.eventLoop().runCallback(callback, this.globalObject, context, data); return true; } @@ -542,16 +521,13 @@ const Handlers = struct { return true; } - pub fn callEventHandlerWithResult(this: *Handlers, comptime event: @Type(.enum_literal), thisValue: JSValue, data: []const JSValue) JSValue { - const callback = @field(this, @tagName(event)); - if (callback == .zero) { - return jsc.JSValue.zero; - } + pub fn callEventHandlerWithResult(this: *Handlers, comptime event: H2FrameParser.js.gc, thisValue: JSValue, data: []const JSValue) JSValue { + const callback = event.get(thisValue) orelse return .zero; return this.vm.eventLoop().runCallbackWithResult(callback, this.globalObject, thisValue, data); } - pub fn fromJS(globalObject: *jsc.JSGlobalObject, opts: jsc.JSValue) bun.JSError!Handlers { + pub fn fromJS(globalObject: *jsc.JSGlobalObject, opts: jsc.JSValue, thisValue: jsc.JSValue) bun.JSError!Handlers { var handlers = Handlers{ .vm = globalObject.bunVM(), .globalObject = globalObject, @@ -587,7 +563,7 @@ const Handlers = struct { return globalObject.throwInvalidArguments("Expected \"{s}\" callback to be a function", .{pair[1]}); } - @field(handlers, pair.@"0") = callback_value.withAsyncContextIfNeeded(globalObject); + @field(H2FrameParser.js.gc, pair.@"0").set(thisValue, globalObject, callback_value.withAsyncContextIfNeeded(globalObject)); } } @@ -596,11 +572,11 @@ const Handlers = struct { return globalObject.throwInvalidArguments("Expected \"error\" callback to be a function", .{}); } - handlers.onError = callback_value.withAsyncContextIfNeeded(globalObject); + H2FrameParser.js.gc.onError.set(thisValue, globalObject, callback_value.withAsyncContextIfNeeded(globalObject)); } // onWrite is required for duplex support or if more than 1 parser is attached to the same socket (unliked) - if (handlers.onWrite == .zero) { + if (H2FrameParser.js.gc.onWrite.get(thisValue) == .zero) { return globalObject.throwInvalidArguments("Expected at least \"write\" callback", .{}); } @@ -614,30 +590,8 @@ const Handlers = struct { }; } - handlers.strong_ctx.set(globalObject, opts); - return handlers; } - - pub fn deinit(this: *Handlers) void { - this.onError = .zero; - this.onWrite = .zero; - this.onStreamError = .zero; - this.onStreamStart = .zero; - this.onStreamHeaders = .zero; - this.onStreamEnd = .zero; - this.onStreamData = .zero; - this.onStreamError = .zero; - this.onLocalSettings = .zero; - this.onRemoteSettings = .zero; - this.onWantTrailers = .zero; - this.onPing = .zero; - this.onEnd = .zero; - this.onGoAway = .zero; - this.onAborted = .zero; - this.onFrameError = .zero; - this.strong_ctx.deinit(); - } }; pub const H2FrameParserConstructor = H2FrameParser.js.getConstructor; @@ -664,7 +618,7 @@ pub const H2FrameParser = struct { const H2FrameParserHiveAllocator = bun.HiveArray(H2FrameParser, 256).Fallback; pub threadlocal var pool: if (ENABLE_ALLOCATOR_POOL) ?*H2FrameParserHiveAllocator else u0 = if (ENABLE_ALLOCATOR_POOL) null else 0; - strong_ctx: jsc.Strong.Optional = .empty, + strong_this: jsc.JSRef = .empty(), globalThis: *jsc.JSGlobalObject, allocator: Allocator, handlers: Handlers, @@ -719,6 +673,7 @@ pub const H2FrameParser = struct { ref_count: RefCount, auto_flusher: AutoFlusher = .{}, + paddingStrategy: PaddingStrategy = .none, threadlocal var shared_request_buffer: [16384]u8 = undefined; /// The streams hashmap may mutate when growing we use this when we need to make sure its safe to iterate over it @@ -762,7 +717,7 @@ pub const H2FrameParser = struct { closeAfterDrain: bool = false, endAfterHeaders: bool = false, isWaitingMoreHeaders: bool = false, - padding: ?u8 = 0, + padding: ?u8 = null, paddingStrategy: PaddingStrategy = .none, rstCode: u32 = 0, streamDependency: u32 = 0, @@ -909,9 +864,9 @@ pub const H2FrameParser = struct { var paddedLen = frameLen + (8 - diff); // limit to maxLen paddedLen = @min(maxLen, paddedLen); - return @min(paddedLen - frameLen, 255); + return @min(paddedLen -| frameLen, 255); }, - .max => return @min(maxLen - frameLen, 255), + .max => return @min(maxLen -| frameLen, 255), } } pub fn flushQueue(this: *Stream, client: *H2FrameParser, written: *usize) FlushState { @@ -976,9 +931,9 @@ pub const H2FrameParser = struct { client.queuedDataSize -= able_to_send.len; written.* += able_to_send.len; - const padding = this.getPadding(able_to_send.len, max_size); - const payload_size = able_to_send.len + (if (padding != 0) padding + 1 else 0); - + const padding = this.getPadding(able_to_send.len, max_size - 1); + const payload_size = able_to_send.len + (if (padding != 0) @as(usize, @intCast(padding)) + 1 else 0); + log("padding: {d} size: {d} max_size: {d} payload_size: {d}", .{ padding, able_to_send.len, max_size, payload_size }); this.remoteUsedWindowSize += payload_size; client.remoteUsedWindowSize += payload_size; @@ -995,9 +950,9 @@ pub const H2FrameParser = struct { _ = dataHeader.write(@TypeOf(writer), writer); if (padding != 0) { var buffer = shared_request_buffer[0..]; - bun.memmove(buffer[1..able_to_send.len], buffer[0..able_to_send.len]); + bun.memmove(buffer[1..][0..able_to_send.len], able_to_send); buffer[0] = padding; - break :brk (writer.write(buffer[0 .. FrameHeader.byteSize + payload_size]) catch 0) != 0; + break :brk (writer.write(buffer[0..payload_size]) catch 0) != 0; } else { break :brk (writer.write(able_to_send) catch 0) != 0; } @@ -1007,8 +962,9 @@ pub const H2FrameParser = struct { client.queuedDataSize -= frame_slice.len; written.* += frame_slice.len; - const padding = this.getPadding(frame_slice.len, max_size); - const payload_size = frame_slice.len + (if (padding != 0) padding + 1 else 0); + const padding = this.getPadding(frame_slice.len, max_size - 1); + const payload_size = frame_slice.len + (if (padding != 0) @as(usize, @intCast(padding)) + 1 else 0); + log("padding: {d} size: {d} max_size: {d} payload_size: {d}", .{ padding, frame_slice.len, max_size, payload_size }); this.remoteUsedWindowSize += payload_size; client.remoteUsedWindowSize += payload_size; var flags: u8 = if (frame.end_stream and !this.waitForTrailers) @intFromEnum(DataFrameFlags.END_STREAM) else 0; @@ -1024,9 +980,9 @@ pub const H2FrameParser = struct { _ = dataHeader.write(@TypeOf(writer), writer); if (padding != 0) { var buffer = shared_request_buffer[0..]; - bun.memmove(buffer[1..frame_slice.len], buffer[0..frame_slice.len]); + bun.memmove(buffer[1..][0..frame_slice.len], frame_slice); buffer[0] = padding; - break :brk (writer.write(buffer[0 .. FrameHeader.byteSize + payload_size]) catch 0) != 0; + break :brk (writer.write(buffer[0..payload_size]) catch 0) != 0; } else { break :brk (writer.write(frame_slice) catch 0) != 0; } @@ -1108,7 +1064,7 @@ pub const H2FrameParser = struct { client.queuedDataSize += frame.len; } - pub fn init(streamIdentifier: u32, initialWindowSize: u32, remoteWindowSize: u32) Stream { + pub fn init(streamIdentifier: u32, initialWindowSize: u32, remoteWindowSize: u32, paddingStrategy: PaddingStrategy) Stream { const stream = Stream{ .id = streamIdentifier, .state = .OPEN, @@ -1117,6 +1073,7 @@ pub const H2FrameParser = struct { .usedWindowSize = 0, .weight = 36, .dataFrameQueue = .{}, + .paddingStrategy = paddingStrategy, }; return stream; } @@ -1216,9 +1173,9 @@ pub const H2FrameParser = struct { /// Calculate the new window size for the connection and the stream /// https://datatracker.ietf.org/doc/html/rfc7540#section-6.9.1 - fn ajustWindowSize(this: *H2FrameParser, stream: ?*Stream, payloadSize: u32) void { + fn adjustWindowSize(this: *H2FrameParser, stream: ?*Stream, payloadSize: u32) void { this.usedWindowSize +|= payloadSize; - log("ajustWindowSize {} {} {} {}", .{ this.usedWindowSize, this.windowSize, this.isServer, payloadSize }); + log("adjustWindowSize {} {} {} {}", .{ this.usedWindowSize, this.windowSize, this.isServer, payloadSize }); if (this.usedWindowSize > this.windowSize) { // we are receiving more data than we are allowed to this.sendGoAway(0, .FLOW_CONTROL_ERROR, "Window size overflow", this.lastStreamID, true); @@ -1480,53 +1437,58 @@ pub const H2FrameParser = struct { _ = this.write(&buffer); } - pub fn dispatch(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: jsc.JSValue) void { + pub fn dispatch(this: *H2FrameParser, comptime event: js.gc, value: jsc.JSValue) void { jsc.markBinding(@src()); - const ctx_value = this.strong_ctx.get() orelse return; value.ensureStillAlive(); - _ = this.handlers.callEventHandler(event, ctx_value, &[_]jsc.JSValue{ ctx_value, value }); + const this_value = this.strong_this.tryGet() orelse return; + const ctx_value = js.gc.context.get(this_value) orelse return; + _ = this.handlers.callEventHandler(event, this_value, ctx_value, &[_]jsc.JSValue{ ctx_value, value }); } - pub fn call(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: jsc.JSValue) JSValue { + pub fn call(this: *H2FrameParser, comptime event: js.gc, value: jsc.JSValue) JSValue { jsc.markBinding(@src()); - const ctx_value = this.strong_ctx.get() orelse return .zero; + const this_value = this.strong_this.tryGet() orelse return .zero; + const ctx_value = js.gc.context.get(this_value) orelse return .zero; value.ensureStillAlive(); - return this.handlers.callEventHandlerWithResult(event, ctx_value, &[_]jsc.JSValue{ ctx_value, value }); + return this.handlers.callEventHandlerWithResult(event, this_value, &[_]jsc.JSValue{ ctx_value, value }); } pub fn dispatchWriteCallback(this: *H2FrameParser, callback: jsc.JSValue) void { jsc.markBinding(@src()); _ = this.handlers.callWriteCallback(callback, &[_]jsc.JSValue{}); } - pub fn dispatchWithExtra(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: jsc.JSValue, extra: jsc.JSValue) void { + pub fn dispatchWithExtra(this: *H2FrameParser, comptime event: js.gc, value: jsc.JSValue, extra: jsc.JSValue) void { jsc.markBinding(@src()); - const ctx_value = this.strong_ctx.get() orelse return; + const this_value = this.strong_this.tryGet() orelse return; + const ctx_value = js.gc.context.get(this_value) orelse return; value.ensureStillAlive(); extra.ensureStillAlive(); - _ = this.handlers.callEventHandler(event, ctx_value, &[_]jsc.JSValue{ ctx_value, value, extra }); + _ = this.handlers.callEventHandler(event, this_value, ctx_value, &[_]jsc.JSValue{ ctx_value, value, extra }); } - pub fn dispatchWith2Extra(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: jsc.JSValue, extra: jsc.JSValue, extra2: jsc.JSValue) void { + pub fn dispatchWith2Extra(this: *H2FrameParser, comptime event: js.gc, value: jsc.JSValue, extra: jsc.JSValue, extra2: jsc.JSValue) void { jsc.markBinding(@src()); - const ctx_value = this.strong_ctx.get() orelse return; + const this_value = this.strong_this.tryGet() orelse return; + const ctx_value = js.gc.context.get(this_value) orelse return; value.ensureStillAlive(); extra.ensureStillAlive(); extra2.ensureStillAlive(); - _ = this.handlers.callEventHandler(event, ctx_value, &[_]jsc.JSValue{ ctx_value, value, extra, extra2 }); + _ = this.handlers.callEventHandler(event, this_value, ctx_value, &[_]jsc.JSValue{ ctx_value, value, extra, extra2 }); } - pub fn dispatchWith3Extra(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: jsc.JSValue, extra: jsc.JSValue, extra2: jsc.JSValue, extra3: jsc.JSValue) void { + pub fn dispatchWith3Extra(this: *H2FrameParser, comptime event: js.gc, value: jsc.JSValue, extra: jsc.JSValue, extra2: jsc.JSValue, extra3: jsc.JSValue) void { jsc.markBinding(@src()); - const ctx_value = this.strong_ctx.get() orelse return; + const this_value = this.strong_this.tryGet() orelse return; + const ctx_value = js.gc.context.get(this_value) orelse return; value.ensureStillAlive(); extra.ensureStillAlive(); extra2.ensureStillAlive(); extra3.ensureStillAlive(); - _ = this.handlers.callEventHandler(event, ctx_value, &[_]jsc.JSValue{ ctx_value, value, extra, extra2, extra3 }); + _ = this.handlers.callEventHandler(event, this_value, ctx_value, &[_]jsc.JSValue{ ctx_value, value, extra, extra2, extra3 }); } fn cork(this: *H2FrameParser) void { if (CORKED_H2) |corked| { @@ -1941,10 +1903,11 @@ pub const H2FrameParser = struct { } pub fn handleDataFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) usize { - log("handleDataFrame {s}", .{if (this.isServer) "server" else "client"}); + log("handleDataFrame {s} data.len: {d}", .{ if (this.isServer) "server" else "client", data.len }); this.readBuffer.reset(); var stream = stream_ orelse { + log("received data frame on stream that does not exist", .{}); this.sendGoAway(frame.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Data frame on connection stream", this.lastStreamID, true); return data.len; }; @@ -1952,14 +1915,16 @@ pub const H2FrameParser = struct { const settings = this.remoteSettings orelse this.localSettings; if (frame.length > settings.maxFrameSize) { + log("received data frame with length: {d} and max frame size: {d}", .{ frame.length, settings.maxFrameSize }); this.sendGoAway(frame.streamIdentifier, ErrorCode.FRAME_SIZE_ERROR, "Invalid dataframe frame size", this.lastStreamID, true); return data.len; } const end: usize = @min(@as(usize, @intCast(this.remainingLength)), data.len); var payload = data[0..end]; - - var data_needed: isize = this.remainingLength; + // window size considering the full frame.length received so far + this.adjustWindowSize(stream, @truncate(payload.len)); + const previous_remaining_length: isize = this.remainingLength; this.remainingLength -= @intCast(end); var padding: u8 = 0; @@ -1973,31 +1938,43 @@ pub const H2FrameParser = struct { } padding = payload[0]; stream.padding = payload[0]; - payload = payload[1..]; } } - if (this.remainingLength < 0) { this.sendGoAway(frame.streamIdentifier, ErrorCode.FRAME_SIZE_ERROR, "Invalid data frame size", this.lastStreamID, true); return data.len; } var emitted = false; - // ignore padding - if (data_needed > padding) { - data_needed -= padding; - log("data received {} {}", .{ padding, payload.len }); - payload = payload[0..@min(@as(usize, @intCast(data_needed)), payload.len)]; - const chunk = this.handlers.binary_type.toJS(payload, this.handlers.globalObject) catch .zero; // TODO: properly propagate exception upwards - // its fine to truncate because is not possible to receive more data than u32 here, usize is only because of slices in size - this.ajustWindowSize(stream, @truncate(payload.len)); - this.dispatchWithExtra(.onStreamData, stream.getIdentifier(), chunk); - emitted = true; - } else { - data_needed = 0; + + const start_idx = frame.length - @as(usize, @intCast(previous_remaining_length)); + if (start_idx < 1 and padding > 0 and payload.len > 0) { + // we need to skip the padding byte + payload = payload[1..]; } + if (payload.len > 0) { + // amount of data received so far + const received_size = frame.length - this.remainingLength; + // max size possible for the chunk without padding and skipping the start_idx + const max_payload_size: usize = frame.length - padding - @as(usize, if (padding > 0) 1 else 0) - start_idx; + payload = payload[0..@min(payload.len, max_payload_size)]; + log("received_size: {d} max_payload_size: {d} padding: {d} payload.len: {d}", .{ + received_size, + max_payload_size, + padding, + payload.len, + }); + + if (payload.len > 0) { + // no padding, just emit the data + const chunk = this.handlers.binary_type.toJS(payload, this.handlers.globalObject) catch .zero; // TODO: properly propagate exception upwards + this.dispatchWithExtra(.onStreamData, stream.getIdentifier(), chunk); + emitted = true; + } + } if (this.remainingLength == 0) { this.currentFrame = null; + stream.padding = null; if (emitted) { // we need to revalidate the stream ptr after emitting onStreamData const entry = this.streams.getEntry(frame.streamIdentifier) orelse return end; @@ -2442,14 +2419,20 @@ pub const H2FrameParser = struct { // new stream open const entry = this.streams.getOrPut(streamIdentifier) catch bun.outOfMemory(); - entry.value_ptr.* = Stream.init(streamIdentifier, this.localSettings.initialWindowSize, if (this.remoteSettings) |s| s.initialWindowSize else DEFAULT_WINDOW_SIZE); - const ctx_value = this.strong_ctx.get() orelse return entry.value_ptr; - const callback = this.handlers.onStreamStart; - if (callback != .zero) { - // we assume that onStreamStart will never mutate the stream hash map - _ = callback.call(this.handlers.globalObject, ctx_value, &[_]jsc.JSValue{ ctx_value, jsc.JSValue.jsNumber(streamIdentifier) }) catch |err| - this.handlers.globalObject.reportActiveExceptionAsUnhandled(err); - } + entry.value_ptr.* = Stream.init( + streamIdentifier, + this.localSettings.initialWindowSize, + if (this.remoteSettings) |s| s.initialWindowSize else DEFAULT_WINDOW_SIZE, + this.paddingStrategy, + ); + const this_value = this.strong_this.tryGet() orelse return entry.value_ptr; + const ctx_value = js.gc.context.get(this_value) orelse return entry.value_ptr; + const callback = js.gc.onStreamStart.get(this_value) orelse return entry.value_ptr; + + // we assume that onStreamStart will never mutate the stream hash map + _ = callback.call(this.handlers.globalObject, ctx_value, &[_]jsc.JSValue{ ctx_value, jsc.JSValue.jsNumber(streamIdentifier) }) catch |err| { + this.handlers.globalObject.reportActiveExceptionAsUnhandled(err); + }; return entry.value_ptr; } @@ -3255,8 +3238,9 @@ pub const H2FrameParser = struct { // the callback will only be called after the last frame is sended stream.queueFrame(this, slice, if (offset >= payload.len) callback else .js_undefined, offset >= payload.len and close); } else { - const padding = stream.getPadding(size, max_size); - const payload_size = size + (if (padding != 0) padding + 1 else 0); + const padding = stream.getPadding(size, max_size - 1); + const payload_size = size + (if (padding != 0) @as(usize, @intCast(padding)) + 1 else 0); + log("padding: {d} size: {d} max_size: {d} payload_size: {d}", .{ padding, size, max_size, payload_size }); stream.remoteUsedWindowSize += payload_size; this.remoteUsedWindowSize += payload_size; var flags: u8 = if (end_stream) @intFromEnum(DataFrameFlags.END_STREAM) else 0; @@ -3267,14 +3251,14 @@ pub const H2FrameParser = struct { .type = @intFromEnum(FrameType.HTTP_FRAME_DATA), .flags = flags, .streamIdentifier = @intCast(stream_id), - .length = payload_size, + .length = @truncate(payload_size), }; _ = dataHeader.write(@TypeOf(writer), writer); if (padding != 0) { var buffer = shared_request_buffer[0..]; - bun.memmove(buffer[1..size], buffer[0..size]); + bun.memmove(buffer[1..][0..slice.len], slice); buffer[0] = padding; - _ = writer.write(buffer[0 .. FrameHeader.byteSize + payload_size]) catch 0; + _ = writer.write(buffer[0..payload_size]) catch 0; } else { _ = writer.write(slice) catch 0; } @@ -4122,7 +4106,8 @@ pub const H2FrameParser = struct { } const padding = stream.getPadding(encoded_size, buffer.len - 1); - const payload_size = encoded_size + (if (padding != 0) padding + 1 else 0); + const payload_size = encoded_size + (if (padding != 0) @as(usize, @intCast(padding)) + 1 else 0); + log("padding: {d} size: {d} max_size: {d} payload_size: {d}", .{ padding, encoded_size, buffer.len - 1, payload_size }); if (padding != 0) { flags |= @intFromEnum(HeadersFrameFlags.PADDED); } @@ -4150,7 +4135,7 @@ pub const H2FrameParser = struct { _ = priority.write(@TypeOf(writer), writer); } if (padding != 0) { - bun.memmove(buffer[1..encoded_size], buffer[0..encoded_size]); + bun.memmove(buffer[1..][0..encoded_size], buffer[0..encoded_size]); buffer[0] = padding; } _ = writer.write(buffer[0..payload_size]) catch 0; @@ -4269,7 +4254,7 @@ pub const H2FrameParser = struct { } } - pub fn constructor(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!*H2FrameParser { + pub fn constructor(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame, thisValue: jsc.JSValue) bun.JSError!*H2FrameParser { const args_list = callframe.arguments_old(1); if (args_list.len < 1) { return globalObject.throw("Expected 1 argument", .{}); @@ -4287,8 +4272,7 @@ pub const H2FrameParser = struct { if (try options.get(globalObject, "handlers")) |handlers_| { handler_js = handlers_; } - var handlers = try Handlers.fromJS(globalObject, handler_js); - errdefer handlers.deinit(); + const handlers = try Handlers.fromJS(globalObject, handler_js, thisValue); var this = brk: { if (ENABLE_ALLOCATOR_POOL) { @@ -4397,6 +4381,15 @@ pub const H2FrameParser = struct { this.maxSendHeaderBlockLength = @bitCast(max_send_header_block_length.toInt32()); } } + if (try settings_js.get(globalObject, "paddingStrategy")) |padding_strategy| { + if (padding_strategy.isNumber()) { + this.paddingStrategy = switch (padding_strategy.to(u32)) { + 1 => .aligned, + 2 => .max, + else => .none, + }; + } + } } } var is_server = false; @@ -4405,7 +4398,9 @@ pub const H2FrameParser = struct { } this.isServer = is_server; - this.strong_ctx.set(globalObject, context_obj); + js.gc.context.set(thisValue, globalObject, context_obj); + + this.strong_this.setStrong(thisValue, globalObject); this.hpack = lshpack.HPACK.init(this.localSettings.headerTableSize); if (is_server) { @@ -4424,6 +4419,10 @@ pub const H2FrameParser = struct { stream.freeResources(this, false); } this.detach(); + if (this.strong_this.tryGet()) |this_value| { + js.gc.context.clear(this_value, this.globalThis); + this.strong_this.setWeak(this_value); + } return .js_undefined; } /// be careful when calling detach be sure that the socket is closed and the parser not accesible anymore @@ -4432,8 +4431,7 @@ pub const H2FrameParser = struct { this.uncork(); this.unregisterAutoFlush(); this.detachNativeSocket(); - this.strong_ctx.deinit(); - this.handlers.deinit(); + this.readBuffer.deinit(); { @@ -4459,6 +4457,7 @@ pub const H2FrameParser = struct { } } this.detach(); + this.strong_this.deinit(); var it = this.streams.valueIterator(); while (it.next()) |stream| { stream.freeResources(this, true); @@ -4470,6 +4469,7 @@ pub const H2FrameParser = struct { pub fn finalize(this: *H2FrameParser) void { log("finalize", .{}); + this.strong_this.deinit(); this.deref(); } }; diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 28efbef99d..119bbe17a3 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -60,8 +60,7 @@ pub fn NewSocket(comptime ssl: bool) type { flags: Flags = .{}, ref_count: RefCount, wrapped: WrappedType = .none, - // TODO: make this optional - handlers: *Handlers, + handlers: ?*Handlers, this_value: jsc.JSValue = .zero, poll_ref: Async.KeepAlive = Async.KeepAlive.init(), ref_pollref_on_connect: bool = true, @@ -208,7 +207,7 @@ pub fn NewSocket(comptime ssl: bool) type { pub fn handleError(this: *This, err_value: jsc.JSValue) void { log("handleError", .{}); - const handlers = this.handlers; + const handlers = this.getHandlers(); var vm = handlers.vm; if (vm.isShuttingDown()) { return; @@ -226,7 +225,7 @@ pub fn NewSocket(comptime ssl: bool) type { jsc.markBinding(@src()); if (this.socket.isDetached()) return; if (this.native_callback.onWritable()) return; - const handlers = this.handlers; + const handlers = this.getHandlers(); const callback = handlers.onWritable; if (callback == .zero) return; @@ -256,8 +255,8 @@ pub fn NewSocket(comptime ssl: bool) type { pub fn onTimeout(this: *This, _: Socket) void { jsc.markBinding(@src()); if (this.socket.isDetached()) return; - log("onTimeout {s}", .{if (this.handlers.is_server) "S" else "C"}); - const handlers = this.handlers; + const handlers = this.getHandlers(); + log("onTimeout {s}", .{if (handlers.is_server) "S" else "C"}); const callback = handlers.onTimeout; if (callback == .zero or this.flags.finalizing) return; if (handlers.vm.isShuttingDown()) { @@ -276,8 +275,13 @@ pub fn NewSocket(comptime ssl: bool) type { }; } + pub fn getHandlers(this: *const This) *Handlers { + return this.handlers orelse @panic("No handlers set on Socket"); + } + pub fn handleConnectError(this: *This, errno: c_int) void { - log("onConnectError {s} ({d}, {d})", .{ if (this.handlers.is_server) "S" else "C", errno, this.ref_count.active_counts }); + const handlers = this.getHandlers(); + log("onConnectError {s} ({d}, {d})", .{ if (handlers.is_server) "S" else "C", errno, this.ref_count.active_counts }); // Ensure the socket is still alive for any defer's we have this.ref(); defer this.deref(); @@ -288,7 +292,6 @@ pub fn NewSocket(comptime ssl: bool) type { defer this.markInactive(); defer if (needs_deref) this.deref(); - const handlers = this.handlers; const vm = handlers.vm; this.poll_ref.unrefOnNextTick(vm); if (vm.isShuttingDown()) { @@ -357,7 +360,7 @@ pub fn NewSocket(comptime ssl: bool) type { pub fn markActive(this: *This) void { if (!this.flags.is_active) { - this.handlers.markActive(); + this.getHandlers().markActive(); this.flags.is_active = true; this.has_pending_activity.store(true, .release); } @@ -385,15 +388,20 @@ pub fn NewSocket(comptime ssl: bool) type { } this.flags.is_active = false; - const vm = this.handlers.vm; - this.handlers.markInactive(); + const handlers = this.getHandlers(); + const vm = handlers.vm; + handlers.markInactive(); this.poll_ref.unref(vm); this.has_pending_activity.store(false, .release); } } + pub fn isServer(this: *const This) bool { + return this.getHandlers().is_server; + } + pub fn onOpen(this: *This, socket: Socket) void { - log("onOpen {s} {*} {} {}", .{ if (this.handlers.is_server) "S" else "C", this, this.socket.isDetached(), this.ref_count.active_counts }); + log("onOpen {s} {*} {} {}", .{ if (this.isServer()) "S" else "C", this, this.socket.isDetached(), this.ref_count.active_counts }); // Ensure the socket remains alive until this is finished this.ref(); defer this.deref(); @@ -425,7 +433,7 @@ pub fn NewSocket(comptime ssl: bool) type { } } if (this.protos) |protos| { - if (this.handlers.is_server) { + if (this.isServer()) { BoringSSL.SSL_CTX_set_alpn_select_cb(BoringSSL.SSL_get_SSL_CTX(ssl_ptr), selectALPNCallback, bun.cast(*anyopaque, this)); } else { _ = BoringSSL.SSL_set_alpn_protos(ssl_ptr, protos.ptr, @as(c_uint, @intCast(protos.len))); @@ -441,7 +449,7 @@ pub fn NewSocket(comptime ssl: bool) type { } } - const handlers = this.handlers; + const handlers = this.getHandlers(); const callback = handlers.onOpen; const handshake_callback = handlers.onHandshake; @@ -493,13 +501,12 @@ pub fn NewSocket(comptime ssl: bool) type { pub fn onEnd(this: *This, _: Socket) void { jsc.markBinding(@src()); if (this.socket.isDetached()) return; - log("onEnd {s}", .{if (this.handlers.is_server) "S" else "C"}); + const handlers = this.getHandlers(); + log("onEnd {s}", .{if (handlers.is_server) "S" else "C"}); // Ensure the socket remains alive until this is finished this.ref(); defer this.deref(); - const handlers = this.handlers; - const callback = handlers.onEnd; if (callback == .zero or handlers.vm.isShuttingDown()) { this.poll_ref.unref(handlers.vm); @@ -525,13 +532,13 @@ pub fn NewSocket(comptime ssl: bool) type { jsc.markBinding(@src()); this.flags.handshake_complete = true; if (this.socket.isDetached()) return; - log("onHandshake {s} ({d})", .{ if (this.handlers.is_server) "S" else "C", success }); + const handlers = this.getHandlers(); + log("onHandshake {s} ({d})", .{ if (handlers.is_server) "S" else "C", success }); const authorized = if (success == 1) true else false; this.flags.authorized = authorized; - const handlers = this.handlers; var callback = handlers.onHandshake; var is_open = false; @@ -567,8 +574,8 @@ pub fn NewSocket(comptime ssl: bool) type { // clean onOpen callback so only called in the first handshake and not in every renegotiation // on servers this would require a different approach but it's not needed because our servers will not call handshake multiple times // servers don't support renegotiation - this.handlers.onOpen.unprotect(); - this.handlers.onOpen = .zero; + this.handlers.?.onOpen.unprotect(); + this.handlers.?.onOpen = .zero; } } else { // call handhsake callback with authorized and authorization error if has one @@ -591,7 +598,8 @@ pub fn NewSocket(comptime ssl: bool) type { pub fn onClose(this: *This, _: Socket, err: c_int, _: ?*anyopaque) void { jsc.markBinding(@src()); - log("onClose {s}", .{if (this.handlers.is_server) "S" else "C"}); + const handlers = this.getHandlers(); + log("onClose {s}", .{if (handlers.is_server) "S" else "C"}); this.detachNativeCallback(); this.socket.detach(); defer this.deref(); @@ -601,7 +609,6 @@ pub fn NewSocket(comptime ssl: bool) type { return; } - const handlers = this.handlers; const vm = handlers.vm; this.poll_ref.unref(vm); @@ -638,10 +645,10 @@ pub fn NewSocket(comptime ssl: bool) type { pub fn onData(this: *This, _: Socket, data: []const u8) void { jsc.markBinding(@src()); if (this.socket.isDetached()) return; - log("onData {s} ({d})", .{ if (this.handlers.is_server) "S" else "C", data.len }); + const handlers = this.getHandlers(); + log("onData {s} ({d})", .{ if (handlers.is_server) "S" else "C", data.len }); if (this.native_callback.onData(data)) return; - const handlers = this.handlers; const callback = handlers.onData; if (callback == .zero or this.flags.finalizing) return; if (handlers.vm.isShuttingDown()) { @@ -680,11 +687,13 @@ pub fn NewSocket(comptime ssl: bool) type { } pub fn getListener(this: *This, _: *jsc.JSGlobalObject) JSValue { - if (!this.handlers.is_server or this.socket.isDetached()) { + const handlers = this.getHandlers(); + + if (!handlers.is_server or this.socket.isDetached()) { return .js_undefined; } - const l: *Listener = @fieldParentPtr("handlers", this.handlers); + const l: *Listener = @fieldParentPtr("handlers", handlers); return l.strong_self.get() orelse .js_undefined; } @@ -1341,13 +1350,14 @@ pub fn NewSocket(comptime ssl: bool) type { return globalObject.throw("Expected \"socket\" option", .{}); }; - const handlers = try Handlers.fromJS(globalObject, socket_obj, this.handlers.is_server); + var prev_handlers = this.getHandlers(); + + const handlers = try Handlers.fromJS(globalObject, socket_obj, prev_handlers.is_server); - var prev_handlers = this.handlers; prev_handlers.unprotect(); - this.handlers.* = handlers; // TODO: this is a memory leak - this.handlers.withAsyncContextIfNeeded(globalObject); - this.handlers.protect(); + this.handlers.?.* = handlers; // TODO: this is a memory leak + this.handlers.?.withAsyncContextIfNeeded(globalObject); + this.handlers.?.protect(); return .js_undefined; } @@ -1389,7 +1399,7 @@ pub fn NewSocket(comptime ssl: bool) type { return .zero; } - var handlers = try Handlers.fromJS(globalObject, socket_obj, this.handlers.is_server); + var handlers = try Handlers.fromJS(globalObject, socket_obj, this.isServer()); if (globalObject.hasException()) { return .zero; @@ -1519,20 +1529,23 @@ pub fn NewSocket(comptime ssl: bool) type { const vm = handlers.vm; var raw_handlers_ptr = bun.default_allocator.create(Handlers) catch bun.outOfMemory(); - raw_handlers_ptr.* = .{ - .vm = vm, - .globalObject = globalObject, - .onOpen = this.handlers.onOpen, - .onClose = this.handlers.onClose, - .onData = this.handlers.onData, - .onWritable = this.handlers.onWritable, - .onTimeout = this.handlers.onTimeout, - .onConnectError = this.handlers.onConnectError, - .onEnd = this.handlers.onEnd, - .onError = this.handlers.onError, - .onHandshake = this.handlers.onHandshake, - .binary_type = this.handlers.binary_type, - .is_server = this.handlers.is_server, + raw_handlers_ptr.* = blk: { + const this_handlers = this.getHandlers(); + break :blk .{ + .vm = vm, + .globalObject = globalObject, + .onOpen = this_handlers.onOpen, + .onClose = this_handlers.onClose, + .onData = this_handlers.onData, + .onWritable = this_handlers.onWritable, + .onTimeout = this_handlers.onTimeout, + .onConnectError = this_handlers.onConnectError, + .onEnd = this_handlers.onEnd, + .onError = this_handlers.onError, + .onHandshake = this_handlers.onHandshake, + .binary_type = this_handlers.binary_type, + .is_server = this_handlers.is_server, + }; }; raw_handlers_ptr.protect(); @@ -1562,7 +1575,7 @@ pub fn NewSocket(comptime ssl: bool) type { tls.markActive(); // we're unrefing the original instance and refing the TLS instance - tls.poll_ref.ref(this.handlers.vm); + tls.poll_ref.ref(this.getHandlers().vm); // mark both instances on socket data if (new_socket.ext(WrappedSocket)) |ctx| { @@ -1574,7 +1587,7 @@ pub fn NewSocket(comptime ssl: bool) type { this.flags.is_active = false; // will free handlers when hits 0 active connections // the connection can be upgraded inside a handler call so we need to guarantee that it will be still alive - this.handlers.markInactive(); + this.getHandlers().markInactive(); this.has_pending_activity.store(false, .release); } diff --git a/src/bun.js/api/bun/socket/Listener.zig b/src/bun.js/api/bun/socket/Listener.zig index d87cd2bf6d..e241a05542 100644 --- a/src/bun.js/api/bun/socket/Listener.zig +++ b/src/bun.js/api/bun/socket/Listener.zig @@ -626,7 +626,9 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock if (ssl_enabled) { var tls = if (prev_maybe_tls) |prev| blk: { - bun.destroy(prev.handlers); + if (prev.handlers) |prev_handlers| { + bun.destroy(prev_handlers); + } bun.assert(prev.this_value != .zero); prev.handlers = handlers_ptr; bun.assert(prev.socket.socket == .detached); diff --git a/src/bun.js/api/bun/socket/tls_socket_functions.zig b/src/bun.js/api/bun/socket/tls_socket_functions.zig index 37e6b84c42..43ee2f9a6b 100644 --- a/src/bun.js/api/bun/socket/tls_socket_functions.zig +++ b/src/bun.js/api/bun/socket/tls_socket_functions.zig @@ -9,7 +9,7 @@ pub fn getServername(this: *This, globalObject: *jsc.JSGlobalObject, _: *jsc.Cal } pub fn setServername(this: *This, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue { - if (this.handlers.is_server) { + if (this.isServer()) { return globalObject.throw("Cannot issue SNI from a TLS server-side socket", .{}); } @@ -118,7 +118,7 @@ pub fn getPeerCertificate(this: *This, globalObject: *jsc.JSGlobalObject, callfr const ssl_ptr = this.socket.ssl() orelse return .js_undefined; if (abbreviated) { - if (this.handlers.is_server) { + if (this.isServer()) { const cert = BoringSSL.SSL_get_peer_certificate(ssl_ptr); if (cert) |x509| { return X509.toJS(x509, globalObject); @@ -130,7 +130,7 @@ pub fn getPeerCertificate(this: *This, globalObject: *jsc.JSGlobalObject, callfr return X509.toJS(cert, globalObject); } var cert: ?*BoringSSL.X509 = null; - if (this.handlers.is_server) { + if (this.isServer()) { cert = BoringSSL.SSL_get_peer_certificate(ssl_ptr); } @@ -380,7 +380,7 @@ pub fn exportKeyingMaterial(this: *This, globalObject: *jsc.JSGlobalObject, call pub fn getEphemeralKeyInfo(this: *This, globalObject: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue { // only available for clients - if (this.handlers.is_server) { + if (this.isServer()) { return JSValue.jsNull(); } var result = JSValue.createEmptyObject(globalObject, 3); @@ -553,7 +553,7 @@ pub fn setVerifyMode(this: *This, globalObject: *jsc.JSGlobalObject, callframe: const request_cert = request_cert_js.toBoolean(); const reject_unauthorized = request_cert_js.toBoolean(); var verify_mode: c_int = BoringSSL.SSL_VERIFY_NONE; - if (this.handlers.is_server) { + if (this.isServer()) { if (request_cert) { verify_mode = BoringSSL.SSL_VERIFY_PEER; if (reject_unauthorized) diff --git a/src/bun.js/api/h2.classes.ts b/src/bun.js/api/h2.classes.ts index 205e9b6c05..1dacd59f15 100644 --- a/src/bun.js/api/h2.classes.ts +++ b/src/bun.js/api/h2.classes.ts @@ -124,6 +124,27 @@ export default [ }, finalize: true, construct: true, + constructNeedsThis: true, klass: {}, + values: [ + "context", + "onError", + "onWrite", + "onStreamError", + "onStreamStart", + "onStreamHeaders", + "onStreamEnd", + "onStreamData", + "onRemoteSettings", + "onLocalSettings", + "onWantTrailers", + "onPing", + "onEnd", + "onGoAway", + "onAborted", + "onAltSvc", + "onOrigin", + "onFrameError", + ], }), ]; diff --git a/src/bun.js/api/server/AnyRequestContext.zig b/src/bun.js/api/server/AnyRequestContext.zig index f79ecca8b2..78c92144a2 100644 --- a/src/bun.js/api/server/AnyRequestContext.zig +++ b/src/bun.js/api/server/AnyRequestContext.zig @@ -199,6 +199,28 @@ pub fn getRequest(self: AnyRequestContext) ?*uws.Request { } } +pub fn onAbort(self: AnyRequestContext, response: uws.AnyResponse) void { + if (self.tagged_pointer.isNull()) { + return; + } + + switch (self.tagged_pointer.tag()) { + @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPServer.RequestContext))) => { + self.tagged_pointer.as(HTTPServer.RequestContext).onAbort(response.TCP); + }, + @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(HTTPSServer.RequestContext))) => { + self.tagged_pointer.as(HTTPSServer.RequestContext).onAbort(response.SSL); + }, + @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPServer.RequestContext))) => { + self.tagged_pointer.as(DebugHTTPServer.RequestContext).onAbort(response.TCP); + }, + @field(Pointer.Tag, bun.meta.typeBaseName(@typeName(DebugHTTPSServer.RequestContext))) => { + self.tagged_pointer.as(DebugHTTPSServer.RequestContext).onAbort(response.SSL); + }, + else => @panic("Unexpected AnyRequestContext tag"), + } +} + pub fn deref(self: AnyRequestContext) void { if (self.tagged_pointer.isNull()) { return; diff --git a/src/bun.js/api/server/NodeHTTPResponse.zig b/src/bun.js/api/server/NodeHTTPResponse.zig index 58c9769ce0..d24a7c1d02 100644 --- a/src/bun.js/api/server/NodeHTTPResponse.zig +++ b/src/bun.js/api/server/NodeHTTPResponse.zig @@ -43,6 +43,15 @@ pub const Flags = packed struct(u8) { is_data_buffered_during_pause: bool = false, /// Did we receive the last chunk of data during pause? is_data_buffered_during_pause_last: bool = false, + + /// Did the user end the request? + pub fn isRequestedCompletedOrEnded(this: *const Flags) bool { + return this.request_has_completed or this.ended; + } + + pub fn isDone(this: *const Flags) bool { + return this.isRequestedCompletedOrEnded() or this.socket_closed; + } }; pub const UpgradeCTX = struct { @@ -334,6 +343,14 @@ pub fn create( return js_this; } +fn isDone(this: *const NodeHTTPResponse) bool { + return this.flags.isDone(); +} + +fn isRequestedCompletedOrEnded(this: *const NodeHTTPResponse) bool { + return this.flags.isRequestedCompletedOrEnded(); +} + pub fn setOnAbortedHandler(this: *NodeHTTPResponse) void { if (this.flags.socket_closed) { return; @@ -346,10 +363,6 @@ pub fn setOnAbortedHandler(this: *NodeHTTPResponse) void { this.upgrade_context.preserveWebSocketHeadersIfNeeded(); } -fn isDone(this: *const NodeHTTPResponse) bool { - return this.flags.request_has_completed or this.flags.ended or this.flags.socket_closed; -} - pub fn getEnded(this: *const NodeHTTPResponse, _: *jsc.JSGlobalObject) jsc.JSValue { return jsc.JSValue.jsBoolean(this.flags.ended); } @@ -430,10 +443,15 @@ extern "C" fn NodeHTTPServer__writeHead_https( pub fn writeHead(this: *NodeHTTPResponse, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { const arguments = callframe.argumentsUndef(3).slice(); - if (this.isDone()) { + if (this.isRequestedCompletedOrEnded()) { return globalObject.ERR(.STREAM_ALREADY_FINISHED, "Stream is already ended", .{}).throw(); } + if (this.flags.socket_closed) { + // We haven't emitted the "close" event yet. + return .js_undefined; + } + const state = this.raw_response.state(); try handleEndedIfNecessary(state, globalObject); @@ -773,6 +791,7 @@ fn onDrain(this: *NodeHTTPResponse, offset: u64, response: uws.AnyResponse) bool // return false means we don't have anything to drain return false; } + const thisValue = this.getThisValue(); const on_writable = js.onWritableGetCached(thisValue) orelse return false; const globalThis = jsc.VirtualMachine.get().global; @@ -791,10 +810,22 @@ fn writeOrEnd( this_value: jsc.JSValue, comptime is_end: bool, ) bun.JSError!jsc.JSValue { - if (this.isDone()) { + if (this.isRequestedCompletedOrEnded()) { return globalObject.ERR(.STREAM_WRITE_AFTER_END, "Stream already ended", .{}).throw(); } + // Loosely mimicking this code: + // function _writeRaw(data, encoding, callback, size) { + // const conn = this[kSocket]; + // if (conn?.destroyed) { + // // The socket was destroyed. If we're still trying to write to it, + // // then we haven't gotten the 'close' event yet. + // return false; + // } + if (this.flags.socket_closed) { + return if (is_end) .js_undefined else jsc.JSValue.jsNumber(0); + } + const state = this.raw_response.state(); if (!state.isResponsePending()) { return globalObject.ERR(.STREAM_WRITE_AFTER_END, "Stream already ended", .{}).throw(); @@ -943,7 +974,7 @@ pub fn setOnAbort(this: *NodeHTTPResponse, thisValue: jsc.JSValue, globalObject: return; } - if (this.isDone() or value.isUndefined()) { + if (this.isRequestedCompletedOrEnded() or value.isUndefined()) { js.onAbortedSetCached(thisValue, globalObject, .zero); } else { js.onAbortedSetCached(thisValue, globalObject, value.withAsyncContextIfNeeded(globalObject)); @@ -1017,7 +1048,9 @@ pub fn write(this: *NodeHTTPResponse, globalObject: *jsc.JSGlobalObject, callfra } pub fn flushHeaders(this: *NodeHTTPResponse, _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!jsc.JSValue { - this.raw_response.flushHeaders(); + if (!this.flags.socket_closed) + this.raw_response.flushHeaders(); + return .js_undefined; } diff --git a/src/bun.js/api/server/SSLConfig.zig b/src/bun.js/api/server/SSLConfig.zig index 707156b0cf..b304cbc5a1 100644 --- a/src/bun.js/api/server/SSLConfig.zig +++ b/src/bun.js/api/server/SSLConfig.zig @@ -1,6 +1,5 @@ const SSLConfig = @This(); -requires_custom_request_ctx: bool = false, server_name: [*c]const u8 = null, key_file_name: [*c]const u8 = null, @@ -10,7 +9,6 @@ ca_file_name: [*c]const u8 = null, dh_params_file_name: [*c]const u8 = null, passphrase: [*c]const u8 = null, -low_memory_mode: bool = false, key: ?[][*c]const u8 = null, key_count: u32 = 0, @@ -29,6 +27,9 @@ protos: ?[*:0]const u8 = null, protos_len: usize = 0, client_renegotiation_limit: u32 = 0, client_renegotiation_window: u32 = 0, +requires_custom_request_ctx: bool = false, +is_using_default_ciphers: bool = true, +low_memory_mode: bool = false, const BlobFileContentResult = struct { data: [:0]const u8, @@ -168,10 +169,18 @@ pub fn deinit(this: *SSLConfig) void { "ca_file_name", "dh_params_file_name", "passphrase", - "ssl_ciphers", "protos", }; + if (!this.is_using_default_ciphers) { + if (this.ssl_ciphers) |slice_ptr| { + const slice = std.mem.span(slice_ptr); + if (slice.len > 0) { + bun.freeSensitive(bun.default_allocator, slice); + } + } + } + inline for (fields) |field| { if (@field(this, field)) |slice_ptr| { const slice = std.mem.span(slice_ptr); @@ -452,10 +461,14 @@ pub fn fromJS(vm: *jsc.VirtualMachine, global: *jsc.JSGlobalObject, obj: jsc.JSV defer sliced.deinit(); if (sliced.len > 0) { result.ssl_ciphers = try bun.default_allocator.dupeZ(u8, sliced.slice()); + result.is_using_default_ciphers = false; any = true; result.requires_custom_request_ctx = true; } } + if (result.is_using_default_ciphers) { + result.ssl_ciphers = global.bunVM().rareData().tlsDefaultCiphers() orelse null; + } if (try obj.getTruthy(global, "serverName") orelse try obj.getTruthy(global, "servername")) |server_name| { var sliced = try server_name.toSlice(global, bun.default_allocator); diff --git a/src/bun.js/api/server/StaticRoute.zig b/src/bun.js/api/server/StaticRoute.zig index 5e79ef6af6..0e504d0ece 100644 --- a/src/bun.js/api/server/StaticRoute.zig +++ b/src/bun.js/api/server/StaticRoute.zig @@ -34,6 +34,14 @@ pub fn initFromAnyBlob(blob: *const AnyBlob, options: InitFromBytesOptions) *Sta headers.append("Content-Type", mime_type.value) catch bun.outOfMemory(); } } + + // Generate ETag if not already present + if (headers.get("etag") == null) { + if (blob.slice().len > 0) { + ETag.appendToHeaders(blob.slice(), &headers) catch bun.outOfMemory(); + } + } + return bun.new(StaticRoute, .{ .ref_count = .init(), .blob = blob.*, @@ -125,8 +133,8 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, argument: jsc.JSValue) bun.JSErro headers.fastRemove(.ContentLength); } - const headers: Headers = if (response.init.headers) |headers| - Headers.from(headers, bun.default_allocator, .{ + var headers: Headers = if (response.init.headers) |h| + Headers.from(h, bun.default_allocator, .{ .body = &blob, }) catch { blob.detach(); @@ -138,6 +146,13 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, argument: jsc.JSValue) bun.JSErro .allocator = bun.default_allocator, }; + // Generate ETag if not already present + if (headers.get("etag") == null) { + if (blob.slice().len > 0) { + try ETag.appendToHeaders(blob.slice(), &headers); + } + } + return bun.new(StaticRoute, .{ .ref_count = .init(), .blob = blob, @@ -154,6 +169,14 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, argument: jsc.JSValue) bun.JSErro // HEAD requests have no body. pub fn onHEADRequest(this: *StaticRoute, req: *uws.Request, resp: AnyResponse) void { + // Check If-None-Match for HEAD requests with 200 status + if (this.status_code == 200) { + if (this.render304NotModifiedIfNoneMatch(req, resp)) { + return; + } + } + + // Continue with normal HEAD request handling req.setYield(false); this.onHEAD(resp); } @@ -176,6 +199,27 @@ fn renderMetadataAndEnd(this: *StaticRoute, resp: AnyResponse) void { } pub fn onRequest(this: *StaticRoute, req: *uws.Request, resp: AnyResponse) void { + const method = bun.http.Method.find(req.method()) orelse .GET; + if (method == .GET) { + this.onGET(req, resp); + } else if (method == .HEAD) { + this.onHEADRequest(req, resp); + } else { + // For other methods, use the original behavior + req.setYield(false); + this.on(resp); + } +} + +pub fn onGET(this: *StaticRoute, req: *uws.Request, resp: AnyResponse) void { + // Check If-None-Match for GET requests with 200 status + if (this.status_code == 200) { + if (this.render304NotModifiedIfNoneMatch(req, resp)) { + return; + } + } + + // Continue with normal GET request handling req.setYield(false); this.on(resp); } @@ -216,7 +260,7 @@ fn onResponseComplete(this: *StaticRoute, resp: AnyResponse) void { this.deref(); } -pub fn doRenderBlob(this: *StaticRoute, resp: AnyResponse, did_finish: *bool) void { +fn doRenderBlob(this: *StaticRoute, resp: AnyResponse, did_finish: *bool) void { // We are not corked // The body is small // Faster to do the memcpy than to do the two network calls @@ -229,7 +273,7 @@ pub fn doRenderBlob(this: *StaticRoute, resp: AnyResponse, did_finish: *bool) vo } } -pub fn doRenderBlobCorked(this: *StaticRoute, resp: AnyResponse, did_finish: *bool) void { +fn doRenderBlobCorked(this: *StaticRoute, resp: AnyResponse, did_finish: *bool) void { this.renderMetadata(resp); this.renderBytes(resp, did_finish); } @@ -306,15 +350,42 @@ pub fn onWithMethod(this: *StaticRoute, method: bun.http.Method, resp: AnyRespon } } +fn render304NotModifiedIfNoneMatch(this: *StaticRoute, req: *uws.Request, resp: AnyResponse) bool { + const if_none_match = req.header("if-none-match") orelse return false; + const etag = this.headers.get("etag") orelse return false; + if (if_none_match.len == 0 or etag.len == 0) { + return false; + } + + if (!ETag.ifNoneMatch(etag, if_none_match)) { + return false; + } + + // Return 304 Not Modified + req.setYield(false); + this.ref(); + if (this.server) |server| { + server.onPendingRequest(); + resp.timeout(server.config().idleTimeout); + } + this.doWriteStatus(304, resp); + this.doWriteHeaders(resp); + resp.endWithoutBody(resp.shouldCloseConnection()); + this.onResponseComplete(resp); + return true; +} + const std = @import("std"); const bun = @import("bun"); const jsc = bun.jsc; -const Headers = bun.http.Headers; const api = bun.schema.api; const AnyServer = jsc.API.AnyServer; const writeStatus = bun.api.server.writeStatus; const AnyBlob = jsc.WebCore.Blob.Any; +const ETag = bun.http.ETag; +const Headers = bun.http.Headers; + const uws = bun.uws; const AnyResponse = uws.AnyResponse; diff --git a/src/bun.js/bindings/BunClientData.h b/src/bun.js/bindings/BunClientData.h index c1901cf70a..7820bf50cc 100644 --- a/src/bun.js/bindings/BunClientData.h +++ b/src/bun.js/bindings/BunClientData.h @@ -36,7 +36,7 @@ enum class UseCustomHeapCellType { Yes, class JSHeapData { WTF_MAKE_NONCOPYABLE(JSHeapData); - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSHeapData); friend class JSVMClientData; public: @@ -77,7 +77,7 @@ DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(JSVMClientData); class JSVMClientData : public JSC::VM::ClientData { WTF_MAKE_NONCOPYABLE(JSVMClientData); - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(JSVMClientData); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(JSVMClientData, JSVMClientData); public: explicit JSVMClientData(JSC::VM&, RefPtr); diff --git a/src/bun.js/bindings/BunGCOutputConstraint.h b/src/bun.js/bindings/BunGCOutputConstraint.h index eaf4ef9ecd..b19d4c37a0 100644 --- a/src/bun.js/bindings/BunGCOutputConstraint.h +++ b/src/bun.js/bindings/BunGCOutputConstraint.h @@ -36,7 +36,7 @@ namespace WebCore { class JSHeapData; class DOMGCOutputConstraint : public JSC::MarkingConstraint { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMEGCOutputConstraint); public: DOMGCOutputConstraint(JSC::VM&, JSHeapData&); diff --git a/src/bun.js/bindings/BunJSCEventLoop.cpp b/src/bun.js/bindings/BunJSCEventLoop.cpp index 9fafa9f6c2..17419ee108 100644 --- a/src/bun.js/bindings/BunJSCEventLoop.cpp +++ b/src/bun.js/bindings/BunJSCEventLoop.cpp @@ -4,33 +4,64 @@ #include #include -// It would be nicer to construct a DropAllLocks in us_loop_run_bun_tick (the only function that -// uses onBeforeWait and onAfterWait), but that code is in C. We use an optional as that lets us -// check whether it's initialized. -static thread_local std::optional drop_all_locks { std::nullopt }; - -extern "C" void WTFTimer__runIfImminent(void* bun_vm); - -// Safe if VM is nullptr -extern "C" void Bun__JSC_onBeforeWait(JSC::VM* vm) +extern "C" void Bun__JSC_onBeforeWait(JSC::VM* _Nonnull vm) { - ASSERT(!drop_all_locks.has_value()); - if (vm) { - bool previouslyHadAccess = vm->heap.hasHeapAccess(); - // sanity check for debug builds to ensure we're not doing a - // use-after-free here - ASSERT(vm->refCount() > 0); - drop_all_locks.emplace(*vm); - if (previouslyHadAccess) { - vm->heap.releaseAccess(); + ASSERT(vm); + const bool previouslyHadAccess = vm->heap.hasHeapAccess(); + // sanity check for debug builds to ensure we're not doing a + // use-after-free here + ASSERT(vm->refCount() > 0); + if (previouslyHadAccess) { + + // Releasing heap access is a balance between: + // 1. CPU usage + // 2. Memory usage + // + // Not releasing heap access causes benchmarks like + // https://github.com/oven-sh/bun/pull/14885 to regress due to + // finalizers not being called quickly enough. + // + // Releasing heap access too often causes high idle CPU usage. + // + // For the following code: + // ``` + // setTimeout(() => {}, 10 * 1000) + // ``` + // + // command time -v when with defaultRemainingRunsUntilSkipReleaseAccess = 0: + // + // Involuntary context switches: 605 + // + // command time -v when with defaultRemainingRunsUntilSkipReleaseAccess = 5: + // + // Involuntary context switches: 350 + // + // command time -v when with defaultRemainingRunsUntilSkipReleaseAccess = 10: + // + // Involuntary context switches: 241 + // + // Also comapre the #14885 benchmark with different values. + // + // The idea here is if you entered JS "recently", running any + // finalizers that might've been waiting to be run is a good idea. + // But if you haven't, like if the process is just waiting on I/O + // then don't bother. + static constexpr int defaultRemainingRunsUntilSkipReleaseAccess = 10; + + static thread_local int remainingRunsUntilSkipReleaseAccess = 0; + + // Note: usage of `didEnterVM` in JSC::VM conflicts with Options::validateDFGClobberize + // We don't need to use that option, so it should be fine. + if (vm->didEnterVM) { + vm->didEnterVM = false; + remainingRunsUntilSkipReleaseAccess = defaultRemainingRunsUntilSkipReleaseAccess; + } + + if (remainingRunsUntilSkipReleaseAccess-- > 0) { + // Constellation: + // > If you are not moving a VM to the different thread, then you can aquire the access and do not need to release + vm->heap.stopIfNecessary(); + vm->didEnterVM = false; } } } - -extern "C" void Bun__JSC_onAfterWait(JSC::VM* vm) -{ - if (vm) { - vm->heap.acquireAccess(); - drop_all_locks.reset(); - } -} diff --git a/src/bun.js/bindings/ConsoleObject.h b/src/bun.js/bindings/ConsoleObject.h index 60608f9b8c..52032f44c3 100644 --- a/src/bun.js/bindings/ConsoleObject.h +++ b/src/bun.js/bindings/ConsoleObject.h @@ -20,7 +20,7 @@ using InspectorScriptProfilerAgent = Inspector::InspectorScriptProfilerAgent; using namespace JSC; class ConsoleObject final : public JSC::ConsoleClient { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(ConsoleObject); public: ~ConsoleObject() final {} diff --git a/src/bun.js/bindings/DOMFormData.h b/src/bun.js/bindings/DOMFormData.h index 8a25f0b60a..c8ceab1817 100644 --- a/src/bun.js/bindings/DOMFormData.h +++ b/src/bun.js/bindings/DOMFormData.h @@ -46,7 +46,7 @@ class HTMLFormElement; DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(DOMFormData); class DOMFormData : public RefCounted, public ContextDestructionObserver { - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(DOMFormData); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(DOMFormData, DOMFormData); public: using FormDataEntryValue = std::variant>; diff --git a/src/bun.js/bindings/ErrorStackTrace.h b/src/bun.js/bindings/ErrorStackTrace.h index 617e416b71..3df2c966c0 100644 --- a/src/bun.js/bindings/ErrorStackTrace.h +++ b/src/bun.js/bindings/ErrorStackTrace.h @@ -132,7 +132,7 @@ public: } bool isConstructor() const { - return m_codeBlock && (JSC::CodeForConstruct == m_codeBlock->specializationKind()); + return m_codeBlock && (JSC::CodeSpecializationKind::CodeForConstruct == m_codeBlock->specializationKind()); } private: diff --git a/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.cpp b/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.cpp index 071f40521c..81039a09de 100644 --- a/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.cpp +++ b/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.cpp @@ -31,7 +31,7 @@ InspectorBunFrontendDevServerAgent::InspectorBunFrontendDevServerAgent(JSC::JSGl InspectorBunFrontendDevServerAgent::~InspectorBunFrontendDevServerAgent() = default; -void InspectorBunFrontendDevServerAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +void InspectorBunFrontendDevServerAgent::didCreateFrontendAndBackend() { } diff --git a/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.h b/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.h index ec4aa23f29..2ba0e33284 100644 --- a/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.h +++ b/src/bun.js/bindings/InspectorBunFrontendDevServerAgent.h @@ -25,7 +25,7 @@ public: virtual ~InspectorBunFrontendDevServerAgent() final; // InspectorAgentBase - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final; + virtual void didCreateFrontendAndBackend() final; virtual void willDestroyFrontendAndBackend(DisconnectReason) final; // BunFrontendDevServerBackendDispatcherHandler diff --git a/src/bun.js/bindings/InspectorHTTPServerAgent.cpp b/src/bun.js/bindings/InspectorHTTPServerAgent.cpp index 9d40ff74ba..cc376d13ac 100644 --- a/src/bun.js/bindings/InspectorHTTPServerAgent.cpp +++ b/src/bun.js/bindings/InspectorHTTPServerAgent.cpp @@ -38,7 +38,7 @@ InspectorHTTPServerAgent::~InspectorHTTPServerAgent() } } -void InspectorHTTPServerAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +void InspectorHTTPServerAgent::didCreateFrontendAndBackend() { } diff --git a/src/bun.js/bindings/InspectorHTTPServerAgent.h b/src/bun.js/bindings/InspectorHTTPServerAgent.h index 3ae1827c6d..432a5fc877 100644 --- a/src/bun.js/bindings/InspectorHTTPServerAgent.h +++ b/src/bun.js/bindings/InspectorHTTPServerAgent.h @@ -28,7 +28,7 @@ public: virtual ~InspectorHTTPServerAgent(); // InspectorAgentBase - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final; + virtual void didCreateFrontendAndBackend() final; virtual void willDestroyFrontendAndBackend(DisconnectReason) final; // HTTPServerBackendDispatcherHandler diff --git a/src/bun.js/bindings/InspectorLifecycleAgent.cpp b/src/bun.js/bindings/InspectorLifecycleAgent.cpp index 6dae95566d..ceaf52a491 100644 --- a/src/bun.js/bindings/InspectorLifecycleAgent.cpp +++ b/src/bun.js/bindings/InspectorLifecycleAgent.cpp @@ -61,7 +61,7 @@ InspectorLifecycleAgent::~InspectorLifecycleAgent() } } -void InspectorLifecycleAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +void InspectorLifecycleAgent::didCreateFrontendAndBackend() { } diff --git a/src/bun.js/bindings/InspectorLifecycleAgent.h b/src/bun.js/bindings/InspectorLifecycleAgent.h index 28cfc79562..d598e7013b 100644 --- a/src/bun.js/bindings/InspectorLifecycleAgent.h +++ b/src/bun.js/bindings/InspectorLifecycleAgent.h @@ -25,7 +25,7 @@ public: virtual ~InspectorLifecycleAgent(); // InspectorAgentBase - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final; + virtual void didCreateFrontendAndBackend() final; virtual void willDestroyFrontendAndBackend(DisconnectReason) final; // LifecycleReporterBackendDispatcherHandler diff --git a/src/bun.js/bindings/InspectorTestReporterAgent.cpp b/src/bun.js/bindings/InspectorTestReporterAgent.cpp index 7543dde846..ff8de98807 100644 --- a/src/bun.js/bindings/InspectorTestReporterAgent.cpp +++ b/src/bun.js/bindings/InspectorTestReporterAgent.cpp @@ -109,7 +109,7 @@ InspectorTestReporterAgent::~InspectorTestReporterAgent() } } -void InspectorTestReporterAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) +void InspectorTestReporterAgent::didCreateFrontendAndBackend() { } diff --git a/src/bun.js/bindings/InspectorTestReporterAgent.h b/src/bun.js/bindings/InspectorTestReporterAgent.h index 3f5b22d0e3..b97bd89dcf 100644 --- a/src/bun.js/bindings/InspectorTestReporterAgent.h +++ b/src/bun.js/bindings/InspectorTestReporterAgent.h @@ -25,7 +25,7 @@ public: virtual ~InspectorTestReporterAgent(); // InspectorAgentBase - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final; + virtual void didCreateFrontendAndBackend() final; virtual void willDestroyFrontendAndBackend(DisconnectReason) final; // TestReporterBackendDispatcherHandler diff --git a/src/bun.js/bindings/JSCommonJSModule.cpp b/src/bun.js/bindings/JSCommonJSModule.cpp index 2b469c502f..c0c740ec02 100644 --- a/src/bun.js/bindings/JSCommonJSModule.cpp +++ b/src/bun.js/bindings/JSCommonJSModule.cpp @@ -123,17 +123,20 @@ static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObj JSFunction* resolveFunction = nullptr; JSFunction* requireFunction = nullptr; const auto initializeModuleObject = [&]() { + SourceCode resolveSourceCode = makeSource("resolve"_s, SourceOrigin(), SourceTaintedOrigin::Untainted); resolveFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireResolveFunctionUnbound(), moduleObject->filename(), - ArgList(), 1, globalObject->commonStrings().resolveString(globalObject)); + ArgList(), 1, globalObject->commonStrings().resolveString(globalObject), resolveSourceCode); RETURN_IF_EXCEPTION(scope, ); + + SourceCode requireSourceCode = makeSource("require"_s, SourceOrigin(), SourceTaintedOrigin::Untainted); requireFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireFunctionUnbound(), moduleObject, - ArgList(), 1, globalObject->commonStrings().requireString(globalObject)); + ArgList(), 1, globalObject->commonStrings().requireString(globalObject), requireSourceCode); RETURN_IF_EXCEPTION(scope, ); requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0); RETURN_IF_EXCEPTION(scope, ); @@ -1549,18 +1552,22 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l globalObject->CommonJSModuleObjectStructure(), filename, filename, dirname, SourceCode()); + SourceCode requireSourceCode = makeSource("require"_s, SourceOrigin(), SourceTaintedOrigin::Untainted); + JSFunction* requireFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireFunctionUnbound(), moduleObject, - ArgList(), 1, globalObject->commonStrings().requireString(globalObject)); + ArgList(), 1, globalObject->commonStrings().requireString(globalObject), requireSourceCode); RETURN_IF_EXCEPTION(scope, nullptr); + SourceCode resolveSourceCode = makeSource("resolve"_s, SourceOrigin(), SourceTaintedOrigin::Untainted); + JSFunction* resolveFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireResolveFunctionUnbound(), moduleObject->filename(), - ArgList(), 1, globalObject->commonStrings().resolveString(globalObject)); + ArgList(), 1, globalObject->commonStrings().resolveString(globalObject), resolveSourceCode); RETURN_IF_EXCEPTION(scope, nullptr); requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0); diff --git a/src/bun.js/bindings/JSFFIFunction.cpp b/src/bun.js/bindings/JSFFIFunction.cpp index 0e5c296607..ee99be8c8e 100644 --- a/src/bun.js/bindings/JSFFIFunction.cpp +++ b/src/bun.js/bindings/JSFFIFunction.cpp @@ -39,7 +39,7 @@ class FFICallbackFunctionWrapper { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(FFICallbackFunctionWrapper); public: JSC::Strong m_function; diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index a852d532fe..29aa728083 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -148,6 +148,7 @@ public: Call, ReturnValue, ReturnThis, + RejectedValue, }; static JSMockImplementation* create(JSC::JSGlobalObject* globalObject, JSC::Structure* structure, Kind kind, JSC::JSValue heldValue, bool isOnce) @@ -962,6 +963,11 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje setReturnValue(createMockResult(vm, globalObject, "return"_s, thisValue)); return JSValue::encode(thisValue); } + case JSMockImplementation::Kind::RejectedValue: { + JSValue rejectedPromise = JSC::JSPromise::rejectedPromise(globalObject, impl->underlyingValue.get()); + setReturnValue(createMockResult(vm, globalObject, "return"_s, rejectedPromise)); + return JSValue::encode(rejectedPromise); + } default: { RELEASE_ASSERT_NOT_REACHED(); } @@ -1033,11 +1039,12 @@ extern "C" JSC::EncodedJSValue JSMockFunction__getCalls(EncodedJSValue encodedVa } return encodedJSUndefined(); } -extern "C" JSC::EncodedJSValue JSMockFunction__getReturns(EncodedJSValue encodedValue) +extern "C" [[ZIG_EXPORT(zero_is_throw)]] JSC::EncodedJSValue JSMockFunction__getReturns(JSC::JSGlobalObject* globalThis, EncodedJSValue encodedValue) { + auto scope = DECLARE_THROW_SCOPE(globalThis->vm()); JSValue value = JSValue::decode(encodedValue); if (auto* mock = tryJSDynamicCast(value)) { - return JSValue::encode(mock->getReturnValues()); + RELEASE_AND_RETURN(scope, JSValue::encode(mock->getReturnValues())); } return encodedJSUndefined(); } @@ -1235,7 +1242,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValue, (JSC::JSGlobalObject * auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); - pushImpl(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0))); + pushImpl(thisObject, globalObject, JSMockImplementation::Kind::RejectedValue, callframe->argument(0)); RELEASE_AND_RETURN(scope, JSValue::encode(thisObject)); } @@ -1248,7 +1255,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce, (JSC::JSGlobalObje auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); - pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::ReturnValue, JSC::JSPromise::rejectedPromise(globalObject, callframe->argument(0))); + pushImplOnce(thisObject, globalObject, JSMockImplementation::Kind::RejectedValue, callframe->argument(0)); RELEASE_AND_RETURN(scope, JSValue::encode(thisObject)); } diff --git a/src/bun.js/bindings/JSPropertyIterator.cpp b/src/bun.js/bindings/JSPropertyIterator.cpp index d9bd3ed52f..5b066bf933 100644 --- a/src/bun.js/bindings/JSPropertyIterator.cpp +++ b/src/bun.js/bindings/JSPropertyIterator.cpp @@ -33,7 +33,7 @@ public: return new JSPropertyIterator(vm, data); } - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSPropertyIterator); }; extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue, size_t* count, bool own_properties_only, bool only_non_index_properties) diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index c9516d8de7..a018612c0c 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -25,6 +25,10 @@ pub const JSValue = enum(i64) { pub const is_pointer = false; pub const JSType = @import("./JSType.zig").JSType; + pub fn format(_: JSValue, comptime _: []const u8, _: std.fmt.FormatOptions, _: anytype) !void { + @compileError("Formatting a JSValue directly is not allowed. Use jsc.ConsoleObject.Formatter"); + } + pub inline fn cast(ptr: anytype) JSValue { return @as(JSValue, @enumFromInt(@as(i64, @bitCast(@intFromPtr(ptr))))); } @@ -62,8 +66,6 @@ pub const JSValue = enum(i64) { ) callconv(.C) void; extern fn JSC__JSValue__forEachPropertyNonIndexed(JSValue0: JSValue, arg1: *JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?*const fn (*JSGlobalObject, ?*anyopaque, *ZigString, JSValue, bool, bool) callconv(.C) void) void; - extern fn JSC__JSValue__forEachProperty(JSValue0: JSValue, arg1: *JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?*const fn (*JSGlobalObject, ?*anyopaque, *ZigString, JSValue, bool, bool) callconv(.C) void) void; - extern fn JSC__JSValue__forEachPropertyOrdered(JSValue0: JSValue, arg1: *JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?*const fn (*JSGlobalObject, ?*anyopaque, *ZigString, JSValue, bool, bool) callconv(.C) void) void; pub fn forEachPropertyNonIndexed( this: JSValue, @@ -80,7 +82,7 @@ pub const JSValue = enum(i64) { ctx: ?*anyopaque, callback: PropertyIteratorFn, ) JSError!void { - return bun.jsc.fromJSHostCallGeneric(globalThis, @src(), JSC__JSValue__forEachProperty, .{ this, globalThis, ctx, callback }); + return bun.cpp.JSC__JSValue__forEachProperty(this, globalThis, ctx, callback); } pub fn forEachPropertyOrdered( @@ -89,7 +91,7 @@ pub const JSValue = enum(i64) { ctx: ?*anyopaque, callback: PropertyIteratorFn, ) JSError!void { - return bun.jsc.fromJSHostCallGeneric(globalThis, @src(), JSC__JSValue__forEachPropertyOrdered, .{ this, globalThis, ctx, callback }); + return bun.cpp.JSC__JSValue__forEachPropertyOrdered(this, globalThis, ctx, callback); } extern fn Bun__JSValue__toNumber(value: JSValue, global: *JSGlobalObject) f64; @@ -1406,18 +1408,18 @@ pub const JSValue = enum(i64) { /// Equivalent to `target[property]`. Calls userland getters/proxies. Can /// throw. Null indicates the property does not exist. JavaScript undefined /// and JavaScript null can exist as a property and is different than zig - /// `null` (property does not exist). + /// `null` (property does not exist), however javascript undefined will return + /// zig null. /// - /// `property` must be either `[]const u8`. A comptime slice may defer to + /// `property` must be `[]const u8`. A comptime slice may defer to /// calling `fastGet`, which use a more optimal code path. This function is /// marked `inline` to allow Zig to determine if `fastGet` should be used /// per invocation. /// /// Cannot handle property names that are numeric indexes. (For this use `getPropertyValue` instead.) /// - pub inline fn get(target: JSValue, global: *JSGlobalObject, property: anytype) JSError!?JSValue { + pub inline fn get(target: JSValue, global: *JSGlobalObject, property_slice: []const u8) JSError!?JSValue { bun.debugAssert(target.isObject()); - const property_slice: []const u8 = property; // must be a slice! // This call requires `get` to be `inline` if (bun.isComptimeKnown(property_slice)) { @@ -1426,12 +1428,7 @@ pub const JSValue = enum(i64) { } } - return switch (try fromJSHostCall(global, @src(), JSC__JSValue__getIfPropertyExistsImpl, .{ - target, - global, - property_slice.ptr, - @intCast(property_slice.len), - })) { + return switch (try bun.cpp.JSC__JSValue__getIfPropertyExistsImpl(target, global, property_slice.ptr, property_slice.len)) { .zero => unreachable, // handled by fromJSHostCall .property_does_not_exist_on_object => null, diff --git a/src/bun.js/bindings/NodeTLS.cpp b/src/bun.js/bindings/NodeTLS.cpp index a846703aef..0fbce49ec9 100644 --- a/src/bun.js/bindings/NodeTLS.cpp +++ b/src/bun.js/bindings/NodeTLS.cpp @@ -72,4 +72,17 @@ JSC_DEFINE_HOST_FUNCTION(getExtraCACertificates, (JSC::JSGlobalObject * globalOb RELEASE_AND_RETURN(scope, JSValue::encode(JSC::objectConstructorFreeze(globalObject, rootCertificates))); } +extern "C" JSC::EncodedJSValue Bun__getTLSDefaultCiphers(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +extern "C" JSC::EncodedJSValue Bun__setTLSDefaultCiphers(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); + +JSC_DEFINE_HOST_FUNCTION(getDefaultCiphers, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + return Bun__getTLSDefaultCiphers(globalObject, callFrame); +} + +JSC_DEFINE_HOST_FUNCTION(setDefaultCiphers, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + return Bun__setTLSDefaultCiphers(globalObject, callFrame); +} + } // namespace Bun diff --git a/src/bun.js/bindings/NodeTLS.h b/src/bun.js/bindings/NodeTLS.h index 296c28c76a..9def4bca54 100644 --- a/src/bun.js/bindings/NodeTLS.h +++ b/src/bun.js/bindings/NodeTLS.h @@ -6,5 +6,7 @@ namespace Bun { BUN_DECLARE_HOST_FUNCTION(Bun__canonicalizeIP); JSC_DECLARE_HOST_FUNCTION(getBundledRootCertificates); JSC_DECLARE_HOST_FUNCTION(getExtraCACertificates); +JSC_DECLARE_HOST_FUNCTION(getDefaultCiphers); +JSC_DECLARE_HOST_FUNCTION(setDefaultCiphers); } diff --git a/src/bun.js/bindings/ScriptExecutionContext.cpp b/src/bun.js/bindings/ScriptExecutionContext.cpp index e43991ceb6..721e437026 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.cpp +++ b/src/bun.js/bindings/ScriptExecutionContext.cpp @@ -69,8 +69,11 @@ static HashMap& allSc ScriptExecutionContext* ScriptExecutionContext::getScriptExecutionContext(ScriptExecutionContextIdentifier identifier) { + if (identifier == 0) { + return nullptr; + } Locker locker { allScriptExecutionContextsMapLock }; - return allScriptExecutionContextsMap().get(identifier); + return allScriptExecutionContextsMap().getOptional(identifier).value_or(nullptr); } template diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h index c17894f892..ed142b9649 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.h +++ b/src/bun.js/bindings/ScriptExecutionContext.h @@ -41,7 +41,7 @@ DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ScriptExecutionContext); #endif class ScriptExecutionContext : public CanMakeWeakPtr, public RefCounted { #if ENABLE(MALLOC_BREAKDOWN) - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ScriptExecutionContext); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ScriptExecutionContext, ScriptExecutionContext); #else WTF_MAKE_TZONE_ALLOCATED(ScriptExecutionContext); #endif diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 91fc27aa34..893e7cca85 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -187,7 +187,7 @@ #include "node/NodeTimers.h" #include "JSConnectionsList.h" #include "JSHTTPParser.h" - +#include #include "JSBunRequest.h" #include "ServerRouteList.h" @@ -4464,7 +4464,8 @@ static JSC::JSPromise* handleResponseOnStreamingAction(JSGlobalObject* lexicalGl JSC::JSLockHolder locker(vm); auto promise = JSC::JSPromise::create(vm, globalObject->promiseStructure()); - auto compiler = JSC::Wasm::StreamingCompiler::create(vm, mode, globalObject, promise, importObject); + auto sourceCode = makeSource("[wasm code]"_s, SourceOrigin(), SourceTaintedOrigin::Untainted); + auto compiler = JSC::Wasm::StreamingCompiler::create(vm, mode, globalObject, promise, importObject, sourceCode); // getBodyStreamOrBytesForWasmStreaming throws the proper exception. Since this is being // executed in a .then(...) callback, throwing is perfectly fine. diff --git a/src/bun.js/bindings/ZigSourceProvider.h b/src/bun.js/bindings/ZigSourceProvider.h index eddb638665..40362880f7 100644 --- a/src/bun.js/bindings/ZigSourceProvider.h +++ b/src/bun.js/bindings/ZigSourceProvider.h @@ -25,7 +25,7 @@ JSC::SourceID sourceIDForSourceURL(const WTF::String& sourceURL); void* sourceMappingForSourceURL(const WTF::String& sourceURL); JSC::SourceOrigin toSourceOrigin(const String& sourceURL, bool isBuiltin); class SourceProvider final : public JSC::SourceProvider { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(SourceProvider); using Base = JSC::SourceProvider; using BytecodeCacheGenerator = JSC::BytecodeCacheGenerator; using UnlinkedFunctionExecutable = JSC::UnlinkedFunctionExecutable; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index afa0178816..47561da6ca 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -3971,9 +3971,9 @@ JSC::EncodedJSValue JSC__JSValue__createObject2(JSC::JSGlobalObject* globalObjec // Returns empty for exception, returns deleted if not found. // Be careful when handling the return value. // Cannot handle numeric index property names! If it is possible that this will be a integer index, use JSC__JSValue__getPropertyValue instead -JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsImpl(JSC::EncodedJSValue JSValue0, +[[ZIG_EXPORT(zero_is_throw)]] JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsImpl(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* globalObject, - const unsigned char* arg1, uint32_t arg2) + const unsigned char* arg1, size_t arg2) { ASSERT_NO_PENDING_EXCEPTION(globalObject); JSValue value = JSC::JSValue::decode(JSValue0); @@ -5870,7 +5870,7 @@ restart: } } -void JSC__JSValue__forEachProperty(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC::JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC::EncodedJSValue JSValue3, bool isSymbol, bool isPrivateSymbol)) +[[ZIG_EXPORT(check_slow)]] void JSC__JSValue__forEachProperty(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* globalObject, void* arg2, void (*iter)([[ZIG_NONNULL]] JSC::JSGlobalObject* arg0, void* ctx, [[ZIG_NONNULL]] ZigString* arg2, JSC::EncodedJSValue JSValue3, bool isSymbol, bool isPrivateSymbol)) { JSC__JSValue__forEachPropertyImpl(JSValue0, globalObject, arg2, iter); } @@ -5880,7 +5880,7 @@ extern "C" void JSC__JSValue__forEachPropertyNonIndexed(JSC::EncodedJSValue JSVa JSC__JSValue__forEachPropertyImpl(JSValue0, globalObject, arg2, iter); } -void JSC__JSValue__forEachPropertyOrdered(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC::JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC::EncodedJSValue JSValue3, bool isSymbol, bool isPrivateSymbol)) +[[ZIG_EXPORT(check_slow)]] void JSC__JSValue__forEachPropertyOrdered(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* globalObject, void* arg2, void (*iter)([[ZIG_NONNULL]] JSC::JSGlobalObject* arg0, void* ctx, [[ZIG_NONNULL]] ZigString* arg2, JSC::EncodedJSValue JSValue3, bool isSymbol, bool isPrivateSymbol)) { JSC::JSValue value = JSC::JSValue::decode(JSValue0); JSC::JSObject* object = value.getObject(); diff --git a/src/bun.js/bindings/blob.h b/src/bun.js/bindings/blob.h index 66eed55cb2..9e59790070 100644 --- a/src/bun.js/bindings/blob.h +++ b/src/bun.js/bindings/blob.h @@ -9,6 +9,9 @@ namespace WebCore { extern "C" void* Blob__dupeFromJS(JSC::EncodedJSValue impl); extern "C" void* Blob__dupe(void* impl); extern "C" void Blob__destroy(void* impl); +extern "C" void* Blob__getDataPtr(JSC::EncodedJSValue blob); +extern "C" size_t Blob__getSize(JSC::EncodedJSValue blob); +extern "C" void* Blob__fromBytes(JSC::JSGlobalObject* globalThis, const void* ptr, size_t len); class Blob : public RefCounted { public: @@ -26,6 +29,11 @@ public: return adoptRef(*new Blob(implPtr)); } + static RefPtr create(std::span bytes, JSC::JSGlobalObject* globalThis) + { + return adoptRef(*new Blob(Blob__fromBytes(globalThis, bytes.data(), bytes.size()))); + } + static RefPtr create(void* ptr) { void* implPtr = Blob__dupe(ptr); diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig index 2544e94951..d5fd4778bc 100644 --- a/src/bun.js/bindings/generated_classes_list.zig +++ b/src/bun.js/bindings/generated_classes_list.zig @@ -21,6 +21,7 @@ pub const Classes = struct { pub const ExpectStringContaining = jsc.Expect.ExpectStringContaining; pub const ExpectStringMatching = jsc.Expect.ExpectStringMatching; pub const ExpectArrayContaining = jsc.Expect.ExpectArrayContaining; + pub const ExpectTypeOf = jsc.Expect.ExpectTypeOf; pub const FileSystemRouter = api.FileSystemRouter; pub const Glob = api.Glob; pub const ShellInterpreter = api.Shell.Interpreter; diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index db641387cc..d9f3418338 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -227,7 +227,6 @@ CPP_DECL JSC::EncodedJSValue JSC__JSValue__bigIntSum(JSC::JSGlobalObject* arg0, CPP_DECL void JSC__JSValue__getClassName(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1, ZigString* arg2); CPP_DECL JSC::EncodedJSValue JSC__JSValue__getErrorsProperty(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1); CPP_DECL JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); -CPP_DECL JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsImpl(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1, const unsigned char* arg2, uint32_t arg3); CPP_DECL double JSC__JSValue__getLengthIfPropertyExistsInternal(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1); CPP_DECL void JSC__JSValue__getNameProperty(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1, ZigString* arg2); CPP_DECL JSC::EncodedJSValue JSC__JSValue__getPrototype(JSC::EncodedJSValue JSValue0, JSC::JSGlobalObject* arg1); diff --git a/src/bun.js/bindings/root.h b/src/bun.js/bindings/root.h index 8894cfe38a..93e70d3859 100644 --- a/src/bun.js/bindings/root.h +++ b/src/bun.js/bindings/root.h @@ -100,5 +100,6 @@ // can be nothrow | zero_is_throw | check_slow #define ZIG_EXPORT(...) +#define ZIG_NONNULL #endif diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 8a059c7e66..50a6364bdb 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -202,7 +202,7 @@ static inline JSC::JSValue jsBigIntFromSQLite(JSC::JSGlobalObject* globalObject, DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(VersionSqlite3); class VersionSqlite3 { - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(VersionSqlite3); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(VersionSqlite3, VersionSqlite3); public: explicit VersionSqlite3(sqlite3* db) diff --git a/src/bun.js/bindings/sqlite/sqlite3.c b/src/bun.js/bindings/sqlite/sqlite3.c index b689c8713d..e218709dfb 100644 --- a/src/bun.js/bindings/sqlite/sqlite3.c +++ b/src/bun.js/bindings/sqlite/sqlite3.c @@ -1,7 +1,7 @@ // clang-format off /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.50.3. By combining all the individual C code files into this +** version 3.50.4. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -19,7 +19,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** 3ce993b8657d6d9deda380a93cdd6404a8c8 with changes in files: +** 4d8adfb30e03f9cf27f800a2c1ba3c48fb4c with changes in files: ** ** */ @@ -466,9 +466,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.50.3" -#define SQLITE_VERSION_NUMBER 3050003 -#define SQLITE_SOURCE_ID "2025-07-17 13:25:10 3ce993b8657d6d9deda380a93cdd6404a8c8ba1b185b2bc423703e41ae5f2543" +#define SQLITE_VERSION "3.50.4" +#define SQLITE_VERSION_NUMBER 3050004 +#define SQLITE_SOURCE_ID "2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -19441,6 +19441,7 @@ struct Expr { Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL ** for a column of an index on an expression */ Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */ + int nReg; /* TK_NULLS: Number of registers to NULL out */ struct { /* TK_IN, TK_SELECT, and TK_EXISTS */ int iAddr; /* Subroutine entry address */ int regReturn; /* Register used to hold return address */ @@ -21475,6 +21476,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int) SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprNullRegisterRange(Parse*, int, int); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); @@ -115242,6 +115244,12 @@ expr_code_doover: sqlite3VdbeLoadString(v, target, pExpr->u.zToken); return target; } + case TK_NULLS: { + /* Set a range of registers to NULL. pExpr->y.nReg registers starting + ** with target */ + sqlite3VdbeAddOp3(v, OP_Null, 0, target, target + pExpr->y.nReg - 1); + return target; + } default: { /* Make NULL the default case so that if a bug causes an illegal ** Expr node to be passed into this function, it will be handled @@ -115926,6 +115934,25 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( return regDest; } +/* +** Make arrangements to invoke OP_Null on a range of registers +** during initialization. +*/ +SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3ExprNullRegisterRange( + Parse *pParse, /* Parsing context */ + int iReg, /* First register to set to NULL */ + int nReg /* Number of sequential registers to NULL out */ +){ + u8 okConstFactor = pParse->okConstFactor; + Expr t; + memset(&t, 0, sizeof(t)); + t.op = TK_NULLS; + t.y.nReg = nReg; + pParse->okConstFactor = 1; + sqlite3ExprCodeRunJustOnce(pParse, &t, iReg); + pParse->okConstFactor = okConstFactor; +} + /* ** Generate code to evaluate an expression and store the results ** into a register. Return the register number where the results @@ -153176,6 +153203,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); VdbeComment((v, "clear abort flag")); sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); + sqlite3ExprNullRegisterRange(pParse, iAMem, pGroupBy->nExpr); /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or @@ -168471,6 +168499,7 @@ static int whereLoopAddBtree( pNew->u.btree.nEq = 0; pNew->u.btree.nBtm = 0; pNew->u.btree.nTop = 0; + pNew->u.btree.nDistinctCol = 0; pNew->nSkip = 0; pNew->nLTerm = 0; pNew->iSortIdx = 0; @@ -169539,8 +169568,6 @@ static i8 wherePathSatisfiesOrderBy( obSat = obDone; } break; - }else if( wctrlFlags & WHERE_DISTINCTBY ){ - pLoop->u.btree.nDistinctCol = 0; } iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; @@ -257281,7 +257308,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2025-07-17 13:25:10 3ce993b8657d6d9deda380a93cdd6404a8c8ba1b185b2bc423703e41ae5f2543", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3", -1, SQLITE_TRANSIENT); } /* diff --git a/src/bun.js/bindings/sqlite/sqlite3_local.h b/src/bun.js/bindings/sqlite/sqlite3_local.h index 1396f94daa..c7ba6ba52e 100644 --- a/src/bun.js/bindings/sqlite/sqlite3_local.h +++ b/src/bun.js/bindings/sqlite/sqlite3_local.h @@ -147,9 +147,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.50.3" -#define SQLITE_VERSION_NUMBER 3050003 -#define SQLITE_SOURCE_ID "2025-07-17 13:25:10 3ce993b8657d6d9deda380a93cdd6404a8c8ba1b185b2bc423703e41ae5f2543" +#define SQLITE_VERSION "3.50.4" +#define SQLITE_VERSION_NUMBER 3050004 +#define SQLITE_SOURCE_ID "2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3" /* ** CAPI3REF: Run-Time Library Version Numbers diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h index cfe8e1f653..44063bfc74 100644 --- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h @@ -10,7 +10,7 @@ using namespace JSC; class DOMClientIsoSubspaces { WTF_MAKE_NONCOPYABLE(DOMClientIsoSubspaces); - WTF_MAKE_FAST_ALLOCATED(DOMClientIsoSubspaces); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMClientIsoSubspaces); public: DOMClientIsoSubspaces() = default; diff --git a/src/bun.js/bindings/webcore/DOMConstructors.h b/src/bun.js/bindings/webcore/DOMConstructors.h index e2feb50296..d83ef6cfe3 100644 --- a/src/bun.js/bindings/webcore/DOMConstructors.h +++ b/src/bun.js/bindings/webcore/DOMConstructors.h @@ -868,7 +868,7 @@ static constexpr unsigned numberOfDOMConstructors = numberOfDOMConstructorsBase class DOMConstructors { WTF_MAKE_NONCOPYABLE(DOMConstructors); - WTF_MAKE_FAST_ALLOCATED(DOMConstructors); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMConstructors); public: using ConstructorArray = std::array, numberOfDOMConstructors>; diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h index 9335b8a3f8..ee4b3c2147 100644 --- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h @@ -11,7 +11,7 @@ using namespace JSC; class DOMIsoSubspaces { WTF_MAKE_NONCOPYABLE(DOMIsoSubspaces); - WTF_MAKE_FAST_ALLOCATED(DOMIsoSubspaces); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMIsoSubspaces); public: DOMIsoSubspaces() = default; diff --git a/src/bun.js/bindings/webcore/DOMPromiseProxy.h b/src/bun.js/bindings/webcore/DOMPromiseProxy.h index 70d42122b7..765528460b 100644 --- a/src/bun.js/bindings/webcore/DOMPromiseProxy.h +++ b/src/bun.js/bindings/webcore/DOMPromiseProxy.h @@ -35,7 +35,7 @@ namespace WebCore { template class DOMPromiseProxy { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMPromiseProxy); public: using Value = typename IDLType::StorageType; @@ -62,7 +62,7 @@ private: template<> class DOMPromiseProxy { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMPromiseProxy); public: DOMPromiseProxy() = default; @@ -88,7 +88,7 @@ private: // FontFace and FontFaceSet. template class DOMPromiseProxyWithResolveCallback { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMPromiseProxyWithResolveCallback); public: using ResolveCallback = Function; diff --git a/src/bun.js/bindings/webcore/EventContext.h b/src/bun.js/bindings/webcore/EventContext.h index 13f0469eb8..41214c9d3c 100644 --- a/src/bun.js/bindings/webcore/EventContext.h +++ b/src/bun.js/bindings/webcore/EventContext.h @@ -35,7 +35,7 @@ namespace WebCore { class EventContext { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(EventContext); public: using EventInvokePhase = EventTarget::EventInvokePhase; diff --git a/src/bun.js/bindings/webcore/EventNames.h b/src/bun.js/bindings/webcore/EventNames.h index 600be7daf6..dfd9feccd6 100644 --- a/src/bun.js/bindings/webcore/EventNames.h +++ b/src/bun.js/bindings/webcore/EventNames.h @@ -42,7 +42,7 @@ namespace WebCore { struct EventNames { WTF_MAKE_NONCOPYABLE(EventNames); - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(EventNames); public: #define DOM_EVENT_NAMES_DECLARE(name) const AtomString name##Event; diff --git a/src/bun.js/bindings/webcore/EventSender.h b/src/bun.js/bindings/webcore/EventSender.h index 246329841d..53bd9183e0 100644 --- a/src/bun.js/bindings/webcore/EventSender.h +++ b/src/bun.js/bindings/webcore/EventSender.h @@ -35,7 +35,7 @@ class Page; template class EventSender { WTF_MAKE_NONCOPYABLE(EventSender); - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(EventSender); public: explicit EventSender(const AtomString& eventType); diff --git a/src/bun.js/bindings/webcore/FetchHeaders.h b/src/bun.js/bindings/webcore/FetchHeaders.h index eac56928c7..c7b7d73eb9 100644 --- a/src/bun.js/bindings/webcore/FetchHeaders.h +++ b/src/bun.js/bindings/webcore/FetchHeaders.h @@ -41,7 +41,7 @@ class ScriptExecutionContext; DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(FetchHeaders); class FetchHeaders : public RefCounted { - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(FetchHeaders); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(FetchHeaders, FetchHeaders); public: enum class Guard { diff --git a/src/bun.js/bindings/webcore/JSCallbackData.h b/src/bun.js/bindings/webcore/JSCallbackData.h index aaf58e24b8..4351a5ab5c 100644 --- a/src/bun.js/bindings/webcore/JSCallbackData.h +++ b/src/bun.js/bindings/webcore/JSCallbackData.h @@ -42,7 +42,7 @@ namespace WebCore { // (and synchronization would be slow). class JSCallbackData { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSCallbackData); public: enum class CallbackType { Function, diff --git a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h index 0cb1a98a11..9baae7d982 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h +++ b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h @@ -213,7 +213,7 @@ private: }; class DOMPromiseDeferredBase { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMPromiseDeferredBase); public: DOMPromiseDeferredBase(Ref&& genericPromise) diff --git a/src/bun.js/bindings/webcore/JSEventEmitterCustom.h b/src/bun.js/bindings/webcore/JSEventEmitterCustom.h index 91c9f8732f..e06e79101e 100644 --- a/src/bun.js/bindings/webcore/JSEventEmitterCustom.h +++ b/src/bun.js/bindings/webcore/JSEventEmitterCustom.h @@ -7,7 +7,7 @@ namespace WebCore { // Wrapper type for JSEventEmitter's castedThis because JSDOMWindow and JSWorkerGlobalScope do not inherit JSEventEmitter. class JSEventEmitterWrapper { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSEventEmitterWrapper); public: JSEventEmitterWrapper(EventEmitter& wrapped, JSC::JSObject* wrapper) diff --git a/src/bun.js/bindings/webcore/JSEventTargetCustom.h b/src/bun.js/bindings/webcore/JSEventTargetCustom.h index e719800691..8987f8226d 100644 --- a/src/bun.js/bindings/webcore/JSEventTargetCustom.h +++ b/src/bun.js/bindings/webcore/JSEventTargetCustom.h @@ -32,7 +32,7 @@ namespace WebCore { // Wrapper type for JSEventTarget's castedThis because JSDOMWindow and JSWorkerGlobalScope do not inherit JSEventTarget. class JSEventTargetWrapper { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(JSEventTargetWrapper); public: JSEventTargetWrapper(EventTarget& wrapped, JSC::JSObject& wrapper) diff --git a/src/bun.js/bindings/webcore/JSMessageEventCustom.cpp b/src/bun.js/bindings/webcore/JSMessageEventCustom.cpp index 66dfccb263..e67b3b4b56 100644 --- a/src/bun.js/bindings/webcore/JSMessageEventCustom.cpp +++ b/src/bun.js/bindings/webcore/JSMessageEventCustom.cpp @@ -40,6 +40,7 @@ // #include "JSMessagePort.h" #include #include +#include "blob.h" namespace WebCore { @@ -57,9 +58,13 @@ JSC::JSValue JSMessageEvent::data(JSC::JSGlobalObject& lexicalGlobalObject) cons auto throwScope = DECLARE_THROW_SCOPE(lexicalGlobalObject.vm()); return cachedPropertyValue(throwScope, lexicalGlobalObject, *this, wrapped().cachedData(), [this, &lexicalGlobalObject](JSC::ThrowScope&) { return WTF::switchOn( - wrapped().data(), [this](MessageEvent::JSValueTag) -> JSC::JSValue { return wrapped().jsData().getValue(JSC::jsNull()); }, [this, &lexicalGlobalObject](const Ref& data) { + wrapped().data(), [this](MessageEvent::JSValueTag) -> JSC::JSValue { return wrapped().jsData().getValue(JSC::jsNull()); }, + [this, &lexicalGlobalObject](const Ref& data) { // FIXME: Is it best to handle errors by returning null rather than throwing an exception? - return data->deserialize(lexicalGlobalObject, globalObject(), wrapped().ports(), SerializationErrorMode::NonThrowing); }, [&lexicalGlobalObject](const String& data) { return toJS(lexicalGlobalObject, data); }, [this, &lexicalGlobalObject](const Ref& data) { return toJS>(lexicalGlobalObject, *globalObject(), data); }); + return data->deserialize(lexicalGlobalObject, globalObject(), wrapped().ports(), SerializationErrorMode::NonThrowing); }, + [&lexicalGlobalObject](const String& data) { return toJS(lexicalGlobalObject, data); }, + [this, &lexicalGlobalObject](const Ref& data) { return toJS>(lexicalGlobalObject, *globalObject(), data); }, + [this, &lexicalGlobalObject](const Ref& data) { return toJS>(lexicalGlobalObject, *globalObject(), data); }); }); } diff --git a/src/bun.js/bindings/webcore/JSWebSocket.cpp b/src/bun.js/bindings/webcore/JSWebSocket.cpp index b6e032ab6a..c9475097f9 100644 --- a/src/bun.js/bindings/webcore/JSWebSocket.cpp +++ b/src/bun.js/bindings/webcore/JSWebSocket.cpp @@ -26,7 +26,7 @@ #include "ExtendedDOMClientIsoSubspaces.h" #include "ExtendedDOMIsoSubspaces.h" #include "IDLTypes.h" -// #include "JSBlob.h" +#include "ZigGeneratedClasses.h" #include "JSDOMAttribute.h" #include "JSDOMBinding.h" #include "JSDOMConstructor.h" @@ -632,19 +632,6 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_send2Body(JSC::JS RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.send(data.releaseNonNull()); }))); } -// static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_send3Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) -// { -// auto& vm = JSC::getVM(lexicalGlobalObject); -// auto throwScope = DECLARE_THROW_SCOPE(vm); -// UNUSED_PARAM(throwScope); -// UNUSED_PARAM(callFrame); -// auto& impl = castedThis->wrapped(); -// EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "send"_s, "Blob"_s); }); -// RETURN_IF_EXCEPTION(throwScope, {}); -// RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.send(*data); }))); -// } - static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_send4Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -671,8 +658,12 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_sendOverloadDispa RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_send1Body(lexicalGlobalObject, callFrame, castedThis))); if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits()) RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_send2Body(lexicalGlobalObject, callFrame, castedThis))); - // if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits()) - // RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_send3Body(lexicalGlobalObject, callFrame, castedThis))); + if (distinguishingArg.isObject()) { + if (auto* blob = jsDynamicCast(distinguishingArg)) { + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return castedThis->wrapped().send(blob); }))); + } + } + RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_send4Body(lexicalGlobalObject, callFrame, castedThis))); } return argsCount < 1 ? throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)) : throwVMTypeError(lexicalGlobalObject, throwScope); @@ -740,19 +731,6 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_ping3Body(JSC::JS RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.ping(data.releaseNonNull()); }))); } -// static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_ping4Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) -// { -// auto& vm = JSC::getVM(lexicalGlobalObject); -// auto throwScope = DECLARE_THROW_SCOPE(vm); -// UNUSED_PARAM(throwScope); -// UNUSED_PARAM(callFrame); -// auto& impl = castedThis->wrapped(); -// EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "ping"_s, "Blob"_s); }); -// RETURN_IF_EXCEPTION(throwScope, {}); -// RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.ping(*data); }))); -// } - static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_ping5Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -781,8 +759,11 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pingOverloadDispa RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_ping2Body(lexicalGlobalObject, callFrame, castedThis))); if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits()) RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_ping3Body(lexicalGlobalObject, callFrame, castedThis))); - // if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits()) - // RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_ping4Body(lexicalGlobalObject, callFrame, castedThis))); + if (distinguishingArg.isObject()) { + if (auto* blob = jsDynamicCast(distinguishingArg)) { + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return castedThis->wrapped().ping(blob); }))); + } + } RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_ping5Body(lexicalGlobalObject, callFrame, castedThis))); } return throwVMTypeError(lexicalGlobalObject, throwScope); @@ -829,19 +810,6 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pong3Body(JSC::JS RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.pong(data.releaseNonNull()); }))); } -// static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pong4Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) -// { -// auto& vm = JSC::getVM(lexicalGlobalObject); -// auto throwScope = DECLARE_THROW_SCOPE(vm); -// UNUSED_PARAM(throwScope); -// UNUSED_PARAM(callFrame); -// auto& impl = castedThis->wrapped(); -// EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); -// auto data = convert>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "data"_s, "WebSocket"_s, "pong"_s, "Blob"_s); }); -// RETURN_IF_EXCEPTION(throwScope, {}); -// RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.pong(*data); }))); -// } - static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pong5Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -870,8 +838,11 @@ static inline JSC::EncodedJSValue jsWebSocketPrototypeFunction_pongOverloadDispa RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_pong2Body(lexicalGlobalObject, callFrame, castedThis))); if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits()) RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_pong3Body(lexicalGlobalObject, callFrame, castedThis))); - // if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits()) - // RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_pong4Body(lexicalGlobalObject, callFrame, castedThis))); + if (distinguishingArg.isObject()) { + if (auto* blob = jsDynamicCast(distinguishingArg)) { + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return castedThis->wrapped().pong(blob); }))); + } + } RELEASE_AND_RETURN(throwScope, (jsWebSocketPrototypeFunction_pong5Body(lexicalGlobalObject, callFrame, castedThis))); } return throwVMTypeError(lexicalGlobalObject, throwScope); diff --git a/src/bun.js/bindings/webcore/MessageEvent.cpp b/src/bun.js/bindings/webcore/MessageEvent.cpp index 8fdc58adb4..c8a00d99ed 100644 --- a/src/bun.js/bindings/webcore/MessageEvent.cpp +++ b/src/bun.js/bindings/webcore/MessageEvent.cpp @@ -34,6 +34,7 @@ #include "JSMessageEvent.h" #include #include +#include "blob.h" namespace WebCore { @@ -149,7 +150,7 @@ size_t MessageEvent::memoryCost() const m_data, [](JSValueTag) -> size_t { return 0; }, [](const Ref& data) -> size_t { return data->memoryCost(); }, [](const String& string) -> size_t { return string.sizeInBytes(); }, - // [](const Ref& blob) -> size_t { return blob->size(); }, + [](const Ref& blob) -> size_t { return blob->memoryCost(); }, [](const Ref& buffer) -> size_t { return buffer->byteLength(); }); } diff --git a/src/bun.js/bindings/webcore/MessageEvent.h b/src/bun.js/bindings/webcore/MessageEvent.h index 3d65710df4..3c7bbe0daa 100644 --- a/src/bun.js/bindings/webcore/MessageEvent.h +++ b/src/bun.js/bindings/webcore/MessageEvent.h @@ -39,14 +39,15 @@ namespace WebCore { +class Blob; + class MessageEvent final : public Event { WTF_MAKE_TZONE_ALLOCATED(MessageEvent); public: struct JSValueTag { }; - // using DataType = std::variant, String, Ref, Ref>; - using DataType = std::variant, String, Ref>; + using DataType = std::variant, String, Ref, Ref>; static Ref create(const AtomString& type, DataType&&, const String& origin = {}, const String& lastEventId = {}, RefPtr&& = nullptr, Vector>&& = {}); static Ref create(DataType&&, const String& origin = {}, const String& lastEventId = {}, RefPtr&& = nullptr, Vector>&& = {}); diff --git a/src/bun.js/bindings/webcore/NetworkLoadMetrics.h b/src/bun.js/bindings/webcore/NetworkLoadMetrics.h index 5e1951f84e..b1591cf203 100644 --- a/src/bun.js/bindings/webcore/NetworkLoadMetrics.h +++ b/src/bun.js/bindings/webcore/NetworkLoadMetrics.h @@ -61,7 +61,7 @@ constexpr MonotonicTime reusedTLSConnectionSentinel { MonotonicTime::fromRawSeco struct AdditionalNetworkLoadMetricsForWebInspector; class NetworkLoadMetrics { - WTF_MAKE_FAST_ALLOCATED(NetworkLoadMetrics); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(NetworkLoadMetrics); public: WEBCORE_EXPORT NetworkLoadMetrics(); diff --git a/src/bun.js/bindings/webcore/PerformanceEntry.h b/src/bun.js/bindings/webcore/PerformanceEntry.h index 1fb135c68f..bb4ed94db7 100644 --- a/src/bun.js/bindings/webcore/PerformanceEntry.h +++ b/src/bun.js/bindings/webcore/PerformanceEntry.h @@ -39,7 +39,7 @@ namespace WebCore { DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(PerformanceEntry); class PerformanceEntry : public RefCounted { - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(PerformanceEntry); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(PerformanceEntry, PerformanceEntry); public: virtual ~PerformanceEntry(); diff --git a/src/bun.js/bindings/webcore/PerformanceObserverEntryList.h b/src/bun.js/bindings/webcore/PerformanceObserverEntryList.h index 61f615c888..ac1bc2823a 100644 --- a/src/bun.js/bindings/webcore/PerformanceObserverEntryList.h +++ b/src/bun.js/bindings/webcore/PerformanceObserverEntryList.h @@ -34,7 +34,7 @@ namespace WebCore { class PerformanceEntry; class PerformanceObserverEntryList : public RefCounted { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(PerformanceObserverEntryList); public: static Ref create(Vector>&& entries); diff --git a/src/bun.js/bindings/webcore/PerformanceUserTiming.h b/src/bun.js/bindings/webcore/PerformanceUserTiming.h index 69f734fd73..4973c1f05d 100644 --- a/src/bun.js/bindings/webcore/PerformanceUserTiming.h +++ b/src/bun.js/bindings/webcore/PerformanceUserTiming.h @@ -42,7 +42,7 @@ class Performance; using PerformanceEntryMap = HashMap>>; class PerformanceUserTiming { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(PerformanceUserTiming); public: explicit PerformanceUserTiming(Performance&); diff --git a/src/bun.js/bindings/webcore/ResourceTiming.h b/src/bun.js/bindings/webcore/ResourceTiming.h index b3a763971b..996874cfe8 100644 --- a/src/bun.js/bindings/webcore/ResourceTiming.h +++ b/src/bun.js/bindings/webcore/ResourceTiming.h @@ -42,7 +42,7 @@ class SecurityOrigin; DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ResourceTiming); class ResourceTiming { - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ResourceTiming); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ResourceTiming, ResourceTiming); public: // static ResourceTiming fromMemoryCache(const URL&, const String& initiator const ResourceResponse&, const NetworkLoadMetrics&, const SecurityOrigin&); diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.h b/src/bun.js/bindings/webcore/SerializedScriptValue.h index f3ed0f33d3..11342a26c5 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.h +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.h @@ -86,7 +86,7 @@ using WasmMemoryHandleArray = Vector>; DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(SerializedScriptValue); class SerializedScriptValue : public ThreadSafeRefCounted { - WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(SerializedScriptValue); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(SerializedScriptValue, SerializedScriptValue); public: static SYSV_ABI void writeBytesForBun(CloneSerializer*, const uint8_t*, uint32_t); @@ -249,7 +249,7 @@ void SerializedScriptValue::encode(Encoder& encoder) const for (const auto& videoChunk : m_serializedVideoChunks) encoder << videoChunk->data(); - // FIXME: encode video frames + // FIXME: encode video frames #endif } diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index d337a2f7ab..e1cb1f424a 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -33,7 +33,8 @@ #include "WebSocket.h" #include "WebSocketDeflate.h" #include "headers.h" -// #include "Blob.h" +#include "blob.h" +#include "ZigGeneratedClasses.h" #include "CloseEvent.h" // #include "ContentSecurityPolicy.h" // #include "DOMWindow.h" @@ -564,22 +565,27 @@ ExceptionOr WebSocket::send(ArrayBufferView& arrayBufferView) return {}; } -// ExceptionOr WebSocket::send(Blob& binaryData) -// { -// LOG(Network, "WebSocket %p send() Sending Blob '%s'", this, binaryData.url().stringCenterEllipsizedToLength().utf8().data()); -// if (m_state == CONNECTING) -// return Exception { InvalidStateError }; -// if (m_state == CLOSING || m_state == CLOSED) { -// unsigned payloadSize = static_cast(binaryData.size()); -// m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, payloadSize); -// m_bufferedAmountAfterClose = saturateAdd(m_bufferedAmountAfterClose, getFramingOverhead(payloadSize)); -// return {}; -// } -// m_bufferedAmount = saturateAdd(m_bufferedAmount, binaryData.size()); -// ASSERT(m_channel); -// m_channel->send(binaryData); -// return {}; -// } +WebCore::ExceptionOr WebCore::WebSocket::send(WebCore::JSBlob* blob) +{ + if (m_state == CONNECTING) + return Exception { InvalidStateError }; + if (m_state == CLOSING || m_state == CLOSED) { + return {}; + } + + // Get the blob data and send it using existing binary data path + void* dataPtr = Blob__getDataPtr(JSC::JSValue::encode(blob)); + size_t dataSize = Blob__getSize(JSC::JSValue::encode(blob)); + + if (dataPtr && dataSize > 0) { + this->sendWebSocketData(static_cast(dataPtr), dataSize, Opcode::Binary); + } else { + // Send empty frame for empty blobs + this->sendWebSocketData(nullptr, 0, Opcode::Binary); + } + + return {}; +} void WebSocket::sendWebSocketData(const char* baseAddress, size_t length, const Opcode op) { @@ -957,10 +963,10 @@ String WebSocket::binaryType() const ExceptionOr WebSocket::setBinaryType(const String& binaryType) { - // if (binaryType == "blob"_s) { - // m_binaryType = BinaryType::Blob; - // return {}; - // } + if (binaryType == "blob"_s) { + m_binaryType = BinaryType::Blob; + return {}; + } if (binaryType == "arraybuffer"_s) { m_binaryType = BinaryType::ArrayBuffer; return {}; @@ -1103,10 +1109,26 @@ void WebSocket::didReceiveBinaryData(const AtomString& eventName, const std::spa // inspector->didReceiveWebSocketFrame(WebSocketChannelInspector::createFrame(binaryData.data(), binaryData.size(), WebSocketFrame::OpCode::OpCodeBinary)); // } switch (m_binaryType) { - // case BinaryType::Blob: - // // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient. - // dispatchEvent(MessageEvent::create(Blob::create(scriptExecutionContext(), WTFMove(binaryData), emptyString()), SecurityOrigin::create(m_url)->toString())); - // break; + case BinaryType::Blob: + if (this->hasEventListeners(eventName)) { + // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener + this->incPendingActivityCount(); + RefPtr blob = Blob::create(binaryData, scriptExecutionContext()->jsGlobalObject()); + dispatchEvent(MessageEvent::create(eventName, blob.releaseNonNull(), m_url.string())); + this->decPendingActivityCount(); + return; + } + + if (auto* context = scriptExecutionContext()) { + RefPtr blob = Blob::create(binaryData, context->jsGlobalObject()); + context->postTask([this, name = eventName, blob = blob.releaseNonNull(), protectedThis = Ref { *this }](ScriptExecutionContext& context) { + ASSERT(scriptExecutionContext()); + protectedThis->dispatchEvent(MessageEvent::create(name, blob, protectedThis->m_url.string())); + protectedThis->decPendingActivityCount(); + }); + } + + break; case BinaryType::ArrayBuffer: { if (this->hasEventListeners(eventName)) { // the main reason for dispatching on a separate tick is to handle when you haven't yet attached an event listener @@ -1177,9 +1199,6 @@ void WebSocket::didReceiveBinaryData(const AtomString& eventName, const std::spa break; } - case BinaryType::Blob: { - // TODO: Blob is not supported currently. - } } // }); } @@ -1533,3 +1552,47 @@ extern "C" void WebSocket__decrementPendingActivity(WebCore::WebSocket* webSocke { webSocket->decPendingActivityCount(); } + +WebCore::ExceptionOr WebCore::WebSocket::ping(WebCore::JSBlob* blob) +{ + if (m_state == CONNECTING) + return Exception { InvalidStateError }; + if (m_state == CLOSING || m_state == CLOSED) { + return {}; + } + + // Get the blob data and send it using existing binary data path + void* dataPtr = Blob__getDataPtr(JSC::JSValue::encode(blob)); + size_t dataSize = Blob__getSize(JSC::JSValue::encode(blob)); + + if (dataPtr && dataSize > 0) { + this->sendWebSocketData(static_cast(dataPtr), dataSize, Opcode::Ping); + } else { + // Send empty frame for empty blobs + this->sendWebSocketData(nullptr, 0, Opcode::Ping); + } + + return {}; +} + +WebCore::ExceptionOr WebCore::WebSocket::pong(WebCore::JSBlob* blob) +{ + if (m_state == CONNECTING) + return Exception { InvalidStateError }; + if (m_state == CLOSING || m_state == CLOSED) { + return {}; + } + + // Get the blob data and send it using existing binary data path + void* dataPtr = Blob__getDataPtr(JSC::JSValue::encode(blob)); + size_t dataSize = Blob__getSize(JSC::JSValue::encode(blob)); + + if (dataPtr && dataSize > 0) { + this->sendWebSocketData(static_cast(dataPtr), dataSize, Opcode::Pong); + } else { + // Send empty frame for empty blobs + this->sendWebSocketData(nullptr, 0, Opcode::Pong); + } + + return {}; +} diff --git a/src/bun.js/bindings/webcore/WebSocket.h b/src/bun.js/bindings/webcore/WebSocket.h index eecbcf4e4a..9bdfa028e9 100644 --- a/src/bun.js/bindings/webcore/WebSocket.h +++ b/src/bun.js/bindings/webcore/WebSocket.h @@ -40,6 +40,10 @@ #include "FetchHeaders.h" #include "WebSocketErrorCode.h" +namespace WebCore { +class JSBlob; +} + namespace uWS { template struct WebSocket; @@ -52,7 +56,7 @@ class ArrayBufferView; namespace WebCore { -// class Blob; +class Blob; class WebSocket final : public RefCounted, public EventTargetWithInlineData, public ContextDestructionObserver { WTF_MAKE_TZONE_ALLOCATED(WebSocket); @@ -95,19 +99,19 @@ public: ExceptionOr send(const String& message); ExceptionOr send(JSC::ArrayBuffer&); ExceptionOr send(JSC::ArrayBufferView&); - // ExceptionOr send(Blob&); + ExceptionOr send(JSBlob*); ExceptionOr ping(); ExceptionOr ping(const String& message); ExceptionOr ping(JSC::ArrayBuffer&); ExceptionOr ping(JSC::ArrayBufferView&); - // ExceptionOr ping(Blob&); + ExceptionOr ping(JSBlob*); ExceptionOr pong(); ExceptionOr pong(const String& message); ExceptionOr pong(JSC::ArrayBuffer&); ExceptionOr pong(JSC::ArrayBufferView&); - // ExceptionOr ping(Blob&); + ExceptionOr pong(JSBlob*); ExceptionOr close(std::optional code, const String& reason); ExceptionOr terminate(); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h index cb6ec5d551..b84a2d331d 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmParameters.h @@ -34,7 +34,7 @@ namespace WebCore { class CryptoAlgorithmParameters { - WTF_MAKE_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(CryptoAlgorithmParameters); public: enum class Class { diff --git a/src/bun.js/bindings/webcrypto/CryptoDigest.cpp b/src/bun.js/bindings/webcrypto/CryptoDigest.cpp index e3c83484fb..0c8f3aa5e8 100644 --- a/src/bun.js/bindings/webcrypto/CryptoDigest.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoDigest.cpp @@ -75,7 +75,7 @@ struct CryptoDigestContext { template struct CryptoDigestContextImpl : public CryptoDigestContext { - WTF_MAKE_STRUCT_FAST_ALLOCATED; + WTF_DEPRECATED_MAKE_STRUCT_FAST_ALLOCATED(CryptoDigestContextImpl); static std::unique_ptr create() { diff --git a/src/bun.js/bindings/workaround-missing-symbols.cpp b/src/bun.js/bindings/workaround-missing-symbols.cpp index 928db9754f..15703aa7b9 100644 --- a/src/bun.js/bindings/workaround-missing-symbols.cpp +++ b/src/bun.js/bindings/workaround-missing-symbols.cpp @@ -299,3 +299,5 @@ extern "C" bool icu_hasBinaryProperty(UChar32 cp, unsigned int prop) { return u_hasBinaryProperty(cp, static_cast(prop)); } + +extern "C" __attribute__((weak)) void mi_thread_set_in_threadpool() {} diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index e5aed312d2..326a944945 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -225,10 +225,10 @@ JSC_DEFINE_HOST_FUNCTION(functionMemoryUsageStatistics, } const auto createdSortedTypeCounts = - [&](JSC::TypeCountSet* typeCounts) -> JSC::JSValue { + [&](JSC::TypeCountSet const& typeCounts) -> JSC::JSValue { WTF::Vector> counts; - counts.reserveInitialCapacity(typeCounts->size()); - for (auto& it : *typeCounts) { + counts.reserveInitialCapacity(typeCounts.size()); + for (auto& it : typeCounts) { if (it.value > 0) counts.append( std::make_pair(Identifier::fromString(vm, it.key), it.value)); @@ -264,8 +264,8 @@ JSC_DEFINE_HOST_FUNCTION(functionMemoryUsageStatistics, return objectTypeCounts; }; - JSValue objectTypeCounts = createdSortedTypeCounts(vm.heap.objectTypeCounts().get()); - JSValue protectedCounts = createdSortedTypeCounts(vm.heap.protectedObjectTypeCounts().get()); + JSValue objectTypeCounts = createdSortedTypeCounts(vm.heap.objectTypeCounts()); + JSValue protectedCounts = createdSortedTypeCounts(vm.heap.protectedObjectTypeCounts()); JSObject* object = constructEmptyObject(globalObject); object->putDirect(vm, Identifier::fromString(vm, "objectTypeCounts"_s), diff --git a/src/bun.js/node/node_net_binding.zig b/src/bun.js/node/node_net_binding.zig index 1bb908171b..ee9be71556 100644 --- a/src/bun.js/node/node_net_binding.zig +++ b/src/bun.js/node/node_net_binding.zig @@ -80,7 +80,7 @@ pub fn newDetachedSocket(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFr .socket_context = null, .ref_count = .init(), .protos = null, - .handlers = undefined, + .handlers = null, }); return socket.getThisValue(globalThis); } else { @@ -89,7 +89,7 @@ pub fn newDetachedSocket(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFr .socket_context = null, .ref_count = .init(), .protos = null, - .handlers = undefined, + .handlers = null, }); return socket.getThisValue(globalThis); } diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index cfd8b444b1..f4d5d96b29 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -339,12 +339,12 @@ fn parseOptionDefinitions(globalThis: *JSGlobalObject, options_obj: JSValue, opt } } - log("[OptionDef] \"{s}\" (type={s}, short={s}, multiple={d}, default={?})", .{ + log("[OptionDef] \"{s}\" (type={s}, short={s}, multiple={d}, default={?s})", .{ String.init(long_option), @tagName(option.type), if (!option.short_name.isEmpty()) option.short_name else String.static("none"), @intFromBool(option.multiple), - option.default_value, + if (option.default_value) |dv| bun.tagName(JSValue, dv) else null, }); try option_definitions.append(option); diff --git a/src/bun.js/rare_data.zig b/src/bun.js/rare_data.zig index 5bb371352e..aa22c96454 100644 --- a/src/bun.js/rare_data.zig +++ b/src/bun.js/rare_data.zig @@ -39,6 +39,8 @@ default_csrf_secret: []const u8 = "", valkey_context: ValkeyContext = .{}, +tls_default_ciphers: ?[:0]const u8 = null, + const PipeReadBuffer = [256 * 1024]u8; const DIGESTED_HMAC_256_LEN = 32; pub const AWSSignatureCache = struct { @@ -421,6 +423,31 @@ pub export fn Bun__Process__getStdinFdType(vm: *jsc.VirtualMachine, fd: i32) Std } } +fn setTLSDefaultCiphersFromJS(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { + const vm = globalThis.bunVM(); + const args = callframe.arguments(); + const ciphers = if (args.len > 0) args[0] else .js_undefined; + if (!ciphers.isString()) return globalThis.throwInvalidArgumentTypeValue("ciphers", "string", ciphers); + var sliced = try ciphers.toSlice(globalThis, bun.default_allocator); + defer sliced.deinit(); + vm.rareData().setTLSDefaultCiphers(sliced.slice()); + return .js_undefined; +} + +fn getTLSDefaultCiphersFromJS(globalThis: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!jsc.JSValue { + const vm = globalThis.bunVM(); + const ciphers = vm.rareData().tlsDefaultCiphers() orelse return try bun.String.createUTF8ForJS(globalThis, bun.uws.get_default_ciphers()); + + return try bun.String.createUTF8ForJS(globalThis, ciphers); +} + +comptime { + const js_setTLSDefaultCiphers = jsc.toJSHostFn(setTLSDefaultCiphersFromJS); + @export(&js_setTLSDefaultCiphers, .{ .name = "Bun__setTLSDefaultCiphers" }); + const js_getTLSDefaultCiphers = jsc.toJSHostFn(getTLSDefaultCiphersFromJS); + @export(&js_getTLSDefaultCiphers, .{ .name = "Bun__getTLSDefaultCiphers" }); +} + pub fn spawnIPCContext(rare: *RareData, vm: *jsc.VirtualMachine) *uws.SocketContext { if (rare.spawn_ipc_usockets_context) |ctx| { return ctx; @@ -466,6 +493,17 @@ pub fn s3DefaultClient(rare: *RareData, globalThis: *jsc.JSGlobalObject) jsc.JSV }; } +pub fn tlsDefaultCiphers(this: *RareData) ?[:0]const u8 { + return this.tls_default_ciphers orelse null; +} + +pub fn setTLSDefaultCiphers(this: *RareData, ciphers: []const u8) void { + if (this.tls_default_ciphers) |old_ciphers| { + bun.default_allocator.free(old_ciphers); + } + this.tls_default_ciphers = bun.default_allocator.dupeZ(u8, ciphers) catch bun.outOfMemory(); +} + pub fn defaultCSRFSecret(this: *RareData) []const u8 { if (this.default_csrf_secret.len == 0) { const secret = bun.default_allocator.alloc(u8, 16) catch bun.outOfMemory(); @@ -498,6 +536,11 @@ pub fn deinit(this: *RareData) void { deflate.deinit(); } + if (this.tls_default_ciphers) |ciphers| { + this.tls_default_ciphers = null; + bun.default_allocator.free(ciphers); + } + this.valkey_context.deinit(); } diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index 735e42f2c4..c4a80442a8 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -4153,14 +4153,21 @@ pub const Expect = struct { pub fn toHaveBeenCalled(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { jsc.markBinding(@src()); const thisValue = callframe.this(); + const firstArgument = callframe.argumentsAsArray(1)[0]; defer this.postMatch(globalThis); + if (!firstArgument.isUndefined()) { + return globalThis.throwInvalidArguments("toHaveBeenCalled() must not have an argument", .{}); + } + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenCalled", ""); const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); incrementExpectCallCounter(); if (!calls.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); } const calls_length = try calls.getLength(globalThis); @@ -4191,7 +4198,9 @@ pub const Expect = struct { const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); if (!calls.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); } const calls_length = try calls.getLength(globalThis); @@ -4224,7 +4233,9 @@ pub const Expect = struct { const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); if (!calls.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); } if (arguments.len < 1 or !arguments[0].isUInt32AsAnyInt()) { @@ -4313,22 +4324,26 @@ pub const Expect = struct { const thisValue = callframe.this(); const arguments = callframe.arguments(); defer this.postMatch(globalThis); - const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenCalledWith", "expected"); + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenCalledWith", "...expected"); incrementExpectCallCounter(); const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); if (!calls.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return this.throw(globalThis, comptime getSignature("toHaveBeenCalledWith", "...expected", false), "\n\nMatcher error: received value must be a mock function\nReceived: {any}", .{value.toFmt(&formatter)}); } var pass = false; - if (try calls.getLength(globalThis) > 0) { + const calls_count = @as(u32, @intCast(try calls.getLength(globalThis))); + if (calls_count > 0) { var itr = try calls.arrayIterator(globalThis); while (try itr.next()) |callItem| { if (callItem == .zero or !callItem.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function with calls: {}", .{value}); + // This indicates a malformed mock object, which is an internal error. + return globalThis.throw("Internal error: expected mock call item to be an array of arguments.", .{}); } if (try callItem.getLength(globalThis) != arguments.len) { @@ -4351,18 +4366,70 @@ pub const Expect = struct { } } - const not = this.flags.not; - if (not) pass = !pass; - if (pass) return .js_undefined; - - // handle failure - if (not) { - const signature = comptime getSignature("toHaveBeenCalledWith", "expected", true); - return this.throw(globalThis, signature, "\n\n" ++ "Number of calls: {any}\n", .{calls.getLength(globalThis)}); + if (pass != this.flags.not) { + return .js_undefined; } - const signature = comptime getSignature("toHaveBeenCalledWith", "expected", false); - return this.throw(globalThis, signature, "\n\n" ++ "Number of calls: {any}\n", .{calls.getLength(globalThis)}); + // handle failure + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + + const expected_args_js_array = try JSValue.createEmptyArray(globalThis, arguments.len); + for (arguments, 0..) |arg, i| { + try expected_args_js_array.putIndex(globalThis, @intCast(i), arg); + } + expected_args_js_array.ensureStillAlive(); + + if (this.flags.not) { + const signature = comptime getSignature("toHaveBeenCalledWith", "...expected", true); + return this.throw(globalThis, signature, "\n\nExpected mock function not to have been called with: {any}\nBut it was.", .{ + expected_args_js_array.toFmt(&formatter), + }); + } + const signature = comptime getSignature("toHaveBeenCalledWith", "...expected", false); + + if (calls_count == 0) { + return this.throw(globalThis, signature, "\n\nExpected: {any}\nBut it was not called.", .{ + expected_args_js_array.toFmt(&formatter), + }); + } + + // If there's only one call, provide a nice diff. + if (calls_count == 1) { + const received_call_args = try calls.getIndex(globalThis, 0); + const diff_format = DiffFormatter{ + .expected = expected_args_js_array, + .received = received_call_args, + .globalThis = globalThis, + .not = false, + }; + return this.throw(globalThis, signature, "\n\n{any}\n", .{diff_format}); + } + + // If there are multiple calls, list them all to help debugging. + const list_formatter = AllCallsWithArgsFormatter{ + .globalThis = globalThis, + .calls = calls, + .formatter = &formatter, + }; + + const fmt = + \\ Expected: {any} + \\ Received: + \\{any} + \\ + \\ Number of calls: {d} + ; + + switch (Output.enable_ansi_colors) { + inline else => |colors| { + return this.throw(globalThis, signature, Output.prettyFmt("\n\n" ++ fmt ++ "\n", colors), .{ + expected_args_js_array.toFmt(&formatter), + list_formatter, + calls_count, + }); + }, + } } pub fn toHaveBeenLastCalledWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { @@ -4371,13 +4438,15 @@ pub const Expect = struct { const thisValue = callframe.this(); const arguments = callframe.arguments(); defer this.postMatch(globalThis); - const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenLastCalledWith", "expected"); + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenLastCalledWith", "...expected"); incrementExpectCallCounter(); const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); if (!calls.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return this.throw(globalThis, comptime getSignature("toHaveBeenLastCalledWith", "...expected", false), "\n\nMatcher error: received value must be a mock function\nReceived: {any}", .{value.toFmt(&formatter)}); } const totalCalls: u32 = @truncate(try calls.getLength(globalThis)); @@ -4389,7 +4458,9 @@ pub const Expect = struct { lastCallValue = try calls.getIndex(globalThis, totalCalls - 1); if (!lastCallValue.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function with calls: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function with calls: {any}", .{value.toFmt(&formatter)}); } if (try lastCallValue.getLength(globalThis) != arguments.len) { @@ -4405,22 +4476,41 @@ pub const Expect = struct { } } - const not = this.flags.not; - if (not) pass = !pass; - if (pass) return .js_undefined; + if (pass != this.flags.not) { + return .js_undefined; + } // handle failure var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; defer formatter.deinit(); - const received_fmt = lastCallValue.toFmt(&formatter); - if (not) { - const signature = comptime getSignature("toHaveBeenLastCalledWith", "expected", true); - return this.throw(globalThis, signature, "\n\n" ++ "Received: {any}" ++ "\n\n" ++ "Number of calls: {any}\n", .{ received_fmt, totalCalls }); + const expected_args_js_array = try JSValue.createEmptyArray(globalThis, arguments.len); + for (arguments, 0..) |arg, i| { + try expected_args_js_array.putIndex(globalThis, @intCast(i), arg); + } + expected_args_js_array.ensureStillAlive(); + + if (this.flags.not) { + const signature = comptime getSignature("toHaveBeenLastCalledWith", "...expected", true); + return this.throw(globalThis, signature, "\n\nExpected last call not to be with: {any}\nBut it was.", .{ + expected_args_js_array.toFmt(&formatter), + }); + } + const signature = comptime getSignature("toHaveBeenLastCalledWith", "...expected", false); + + if (totalCalls == 0) { + return this.throw(globalThis, signature, "\n\nExpected: {any}\nBut it was not called.", .{ + expected_args_js_array.toFmt(&formatter), + }); } - const signature = comptime getSignature("toHaveBeenLastCalledWith", "expected", false); - return this.throw(globalThis, signature, "\n\n" ++ "Received: {any}" ++ "\n\n" ++ "Number of calls: {any}\n", .{ received_fmt, totalCalls }); + const diff_format = DiffFormatter{ + .expected = expected_args_js_array, + .received = lastCallValue, + .globalThis = globalThis, + .not = false, + }; + return this.throw(globalThis, signature, "\n\n{any}\n", .{diff_format}); } pub fn toHaveBeenNthCalledWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { @@ -4429,38 +4519,45 @@ pub const Expect = struct { const thisValue = callframe.this(); const arguments = callframe.arguments(); defer this.postMatch(globalThis); - const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenNthCalledWith", "expected"); + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenNthCalledWith", "n, ...expected"); incrementExpectCallCounter(); const calls = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getCalls, .{value}); if (!calls.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return this.throw(globalThis, comptime getSignature("toHaveBeenNthCalledWith", "n, ...expected", false), "\n\nMatcher error: received value must be a mock function\nReceived: {any}", .{value.toFmt(&formatter)}); } - const nthCallNum = if (arguments.len > 0 and arguments[0].isUInt32AsAnyInt()) try arguments[0].coerce(i32, globalThis) else 0; - if (nthCallNum < 1) { - return globalThis.throwInvalidArguments("toHaveBeenNthCalledWith() requires a positive integer argument", .{}); + if (arguments.len == 0 or !arguments[0].isAnyInt()) { + return globalThis.throwInvalidArguments("toHaveBeenNthCalledWith() requires a positive integer as the first argument", .{}); } + const nthCallNumI32 = arguments[0].toInt32(); - const totalCalls = try calls.getLength(globalThis); + if (nthCallNumI32 <= 0) { + return globalThis.throwInvalidArguments("toHaveBeenNthCalledWith() first argument must be a positive integer", .{}); + } + const nthCallNum: u32 = @intCast(nthCallNumI32); + + const totalCalls = @as(u32, @intCast(try calls.getLength(globalThis))); + var pass = totalCalls >= nthCallNum; var nthCallValue: JSValue = .zero; - var pass = totalCalls >= nthCallNum; - if (pass) { - nthCallValue = try calls.getIndex(globalThis, @as(u32, @intCast(nthCallNum)) - 1); + nthCallValue = try calls.getIndex(globalThis, nthCallNum - 1); + const expected_args = arguments[1..]; if (!nthCallValue.jsType().isArray()) { - return globalThis.throw("Expected value must be a mock function with calls: {}", .{value}); + return globalThis.throw("Internal error: expected mock call item to be an array of arguments.", .{}); } - if (try nthCallValue.getLength(globalThis) != (arguments.len - 1)) { + if (try nthCallValue.getLength(globalThis) != expected_args.len) { pass = false; } else { var itr = try nthCallValue.arrayIterator(globalThis); while (try itr.next()) |callArg| { - if (!try callArg.jestDeepEquals(arguments[itr.i], globalThis)) { + if (!try callArg.jestDeepEquals(expected_args[itr.i - 1], globalThis)) { pass = false; break; } @@ -4468,24 +4565,74 @@ pub const Expect = struct { } } - const not = this.flags.not; - if (not) pass = !pass; - if (pass) return .js_undefined; + if (pass != this.flags.not) { + return .js_undefined; + } // handle failure var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; defer formatter.deinit(); - const received_fmt = nthCallValue.toFmt(&formatter); - if (not) { - const signature = comptime getSignature("toHaveBeenNthCalledWith", "expected", true); - return this.throw(globalThis, signature, "\n\n" ++ "n: {any}\n" ++ "Received: {any}" ++ "\n\n" ++ "Number of calls: {any}\n", .{ nthCallNum, received_fmt, totalCalls }); + const expected_args_slice = arguments[1..]; + const expected_args_js_array = try JSValue.createEmptyArray(globalThis, expected_args_slice.len); + for (expected_args_slice, 0..) |arg, i| { + try expected_args_js_array.putIndex(globalThis, @intCast(i), arg); + } + expected_args_js_array.ensureStillAlive(); + + if (this.flags.not) { + const signature = comptime getSignature("toHaveBeenNthCalledWith", "n, ...expected", true); + return this.throw(globalThis, signature, "\n\nExpected call #{d} not to be with: {any}\nBut it was.", .{ + nthCallNum, + expected_args_js_array.toFmt(&formatter), + }); + } + const signature = comptime getSignature("toHaveBeenNthCalledWith", "n, ...expected", false); + + // Handle case where function was not called enough times + if (totalCalls < nthCallNum) { + return this.throw(globalThis, signature, "\n\nThe mock function was called {d} time{s}, but call {d} was requested.", .{ + totalCalls, + if (totalCalls == 1) "" else "s", + nthCallNum, + }); } - const signature = comptime getSignature("toHaveBeenNthCalledWith", "expected", false); - return this.throw(globalThis, signature, "\n\n" ++ "n: {any}\n" ++ "Received: {any}" ++ "\n\n" ++ "Number of calls: {any}\n", .{ nthCallNum, received_fmt, totalCalls }); + // The call existed but didn't match. Show a diff. + const diff_format = DiffFormatter{ + .expected = expected_args_js_array, + .received = nthCallValue, + .globalThis = globalThis, + .not = false, + }; + return this.throw(globalThis, signature, "\n\nCall #{d}:\n{any}\n", .{ nthCallNum, diff_format }); } + const AllCallsWithArgsFormatter = struct { + globalThis: *JSGlobalObject, + calls: JSValue, + formatter: *jsc.ConsoleObject.Formatter, + + pub fn format(self: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + var printed_once = false; + + const calls_count = @as(u32, @intCast(try self.calls.getLength(self.globalThis))); + if (calls_count == 0) { + try writer.writeAll("(no calls)"); + return; + } + + for (0..calls_count) |i| { + if (printed_once) try writer.writeAll("\n"); + printed_once = true; + + try writer.print(" {d: >4}: ", .{i + 1}); + const call_args = try self.calls.getIndex(self.globalThis, @intCast(i)); + try writer.print("{any}", .{call_args.toFmt(self.formatter)}); + } + } + }; + const ReturnStatus = enum { throw, @"return", @@ -4494,93 +4641,476 @@ pub const Expect = struct { pub const Map = bun.ComptimeEnumMap(ReturnStatus); }; - inline fn toHaveReturnedTimesFn(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame, comptime known_index: ?i32) bun.JSError!JSValue { + fn jestMockIterator(globalThis: *JSGlobalObject, value: bun.jsc.JSValue) bun.JSError!bun.jsc.JSArrayIterator { + const returns: bun.jsc.JSValue = try bun.cpp.JSMockFunction__getReturns(globalThis, value); + if (!returns.jsType().isArray()) { + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); + } + + return try returns.arrayIterator(globalThis); + } + fn jestMockReturnObject_type(globalThis: *JSGlobalObject, value: bun.jsc.JSValue) bun.JSError!ReturnStatus { + if (try value.fastGet(globalThis, .type)) |type_string| { + if (type_string.isString()) { + if (try ReturnStatus.Map.fromJS(globalThis, type_string)) |val| return val; + } + } + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function with returns: {any}", .{value.toFmt(&formatter)}); + } + fn jestMockReturnObject_value(globalThis: *JSGlobalObject, value: bun.jsc.JSValue) bun.JSError!JSValue { + return (try value.get(globalThis, "value")) orelse .js_undefined; + } + + inline fn toHaveReturnedTimesFn(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame, comptime mode: enum { toHaveReturned, toHaveReturnedTimes }) bun.JSError!JSValue { jsc.markBinding(@src()); const thisValue = callframe.this(); - const arguments = callframe.arguments_old(1).slice(); + const arguments = callframe.arguments(); defer this.postMatch(globalThis); - const name = comptime if (known_index != null and known_index.? == 0) "toHaveReturned" else "toHaveReturnedTimes"; - - const value: JSValue = try this.getValue(globalThis, thisValue, name, if (known_index != null and known_index.? == 0) "" else "expected"); + const value: JSValue = try this.getValue(globalThis, thisValue, @tagName(mode), "expected"); incrementExpectCallCounter(); - const returns = try bun.jsc.fromJSHostCall(globalThis, @src(), JSMockFunction__getReturns, .{value}); - if (!returns.jsType().isArray()) return globalThis.throw("Expected value must be a mock function: {}", .{value}); + var returns = try jestMockIterator(globalThis, value); - const return_count: i32 = if (known_index) |index| index else brk: { + const expected_success_count: i32 = if (mode == .toHaveReturned) brk: { + if (arguments.len > 0 and !arguments[0].isUndefined()) { + return globalThis.throwInvalidArguments(@tagName(mode) ++ "() must not have an argument", .{}); + } + break :brk 1; + } else brk: { if (arguments.len < 1 or !arguments[0].isUInt32AsAnyInt()) { - return globalThis.throwInvalidArguments(name ++ "() requires 1 non-negative integer argument", .{}); + return globalThis.throwInvalidArguments(@tagName(mode) ++ "() requires 1 non-negative integer argument", .{}); } break :brk try arguments[0].coerce(i32, globalThis); }; var pass = false; - const index: u32 = @as(u32, @intCast(return_count)) -| 1; - const times_value = returns.getDirectIndex( - globalThis, - index, - ); - - const total_count = try returns.getLength(globalThis); - - const return_status: ReturnStatus = brk: { - // Returns is an array of: - // - // { type: "throw" | "incomplete" | "return", value: any} - // - if (total_count >= return_count and times_value.isCell()) { - if (try times_value.get(globalThis, "type")) |type_string| { - if (type_string.isString()) { - break :brk try ReturnStatus.Map.fromJS(globalThis, type_string) orelse { - return globalThis.throw("Expected value must be a mock function with returns: {}", .{value}); - }; - } - } + var actual_success_count: i32 = 0; + var total_call_count: i32 = 0; + while (try returns.next()) |item| { + switch (try jestMockReturnObject_type(globalThis, item)) { + .@"return" => actual_success_count += 1, + else => {}, } + total_call_count += 1; + } - break :brk ReturnStatus.incomplete; + pass = switch (mode) { + .toHaveReturned => actual_success_count >= expected_success_count, + .toHaveReturnedTimes => actual_success_count == expected_success_count, }; - if (globalThis.hasException()) - return .zero; - - pass = return_status == ReturnStatus.@"return"; const not = this.flags.not; if (not) pass = !pass; if (pass) return .js_undefined; - if (!pass and return_status == ReturnStatus.throw) { - const signature = comptime getSignature(name, "expected", false); - const fmt = signature ++ "\n\n" ++ "Function threw an exception\n{any}\n"; - var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; - defer formatter.deinit(); - return globalThis.throwPretty(fmt, .{(try times_value.get(globalThis, "value")).?.toFmt(&formatter)}); - } - switch (not) { inline else => |is_not| { - const signature = comptime getSignature(name, "expected", is_not); - return this.throw(globalThis, signature, "\n\n" ++ "Expected number of successful calls: {d}\n" ++ "Received number of calls: {d}\n", .{ return_count, total_count }); + const signature = comptime getSignature(@tagName(mode), "expected", is_not); + const str: []const u8, const spc: []const u8 = switch (mode) { + .toHaveReturned => switch (not) { + false => .{ ">= ", " " }, + true => .{ "< ", " " }, + }, + .toHaveReturnedTimes => switch (not) { + false => .{ "== ", " " }, + true => .{ "!= ", " " }, + }, + }; + return this.throw(globalThis, signature, + \\ + \\ + \\Expected number of succesful returns: {s}{d} + \\Received number of succesful returns: {s}{d} + \\Received number of calls: {s}{d} + \\ + , .{ str, expected_success_count, spc, actual_success_count, spc, total_call_count }); }, } } pub fn toHaveReturned(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { - return toHaveReturnedTimesFn(this, globalThis, callframe, 1); + return toHaveReturnedTimesFn(this, globalThis, callframe, .toHaveReturned); } pub fn toHaveReturnedTimes(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { - return toHaveReturnedTimesFn(this, globalThis, callframe, null); + return toHaveReturnedTimesFn(this, globalThis, callframe, .toHaveReturnedTimes); } - pub const toHaveReturnedWith = notImplementedJSCFn; - pub const toHaveLastReturnedWith = notImplementedJSCFn; - pub const toHaveNthReturnedWith = notImplementedJSCFn; + // Formatter for when there are multiple returns or errors + const AllCallsFormatter = struct { + globalThis: *JSGlobalObject, + returns: JSValue, + formatter: *jsc.ConsoleObject.Formatter, + + pub fn format(self: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + var printed_once = false; + + var num_returns: i32 = 0; + var num_calls: i32 = 0; + + var iter = try self.returns.arrayIterator(self.globalThis); + while (try iter.next()) |item| { + if (printed_once) try writer.writeAll("\n"); + printed_once = true; + + num_calls += 1; + try writer.print(" {d: >2}: ", .{num_calls}); + + const value = try jestMockReturnObject_value(self.globalThis, item); + switch (try jestMockReturnObject_type(self.globalThis, item)) { + .@"return" => { + try writer.print("{any}", .{value.toFmt(self.formatter)}); + num_returns += 1; + }, + .throw => { + try writer.print("function call threw an error: {any}", .{value.toFmt(self.formatter)}); + }, + .incomplete => { + try writer.print("", .{}); + }, + } + } + } + }; + + const SuccessfulReturnsFormatter = struct { + globalThis: *JSGlobalObject, + successful_returns: *const std.ArrayList(JSValue), + formatter: *jsc.ConsoleObject.Formatter, + + pub fn format(self: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const len = self.successful_returns.items.len; + if (len == 0) return; + + var printed_once = false; + + for (self.successful_returns.items, 1..) |val, i| { + if (printed_once) try writer.writeAll("\n"); + printed_once = true; + + try writer.print(" {d: >4}: ", .{i}); + try writer.print("{any}", .{val.toFmt(self.formatter)}); + } + } + }; + + pub fn toHaveReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { + jsc.markBinding(@src()); + + const thisValue = callframe.this(); + defer this.postMatch(globalThis); + + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveReturnedWith", "expected"); + + const expected = callframe.argumentsAsArray(1)[0]; + incrementExpectCallCounter(); + + const returns = try bun.cpp.JSMockFunction__getReturns(globalThis, value); + if (!returns.jsType().isArray()) { + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); + } + + const calls_count = @as(u32, @intCast(try returns.getLength(globalThis))); + var pass = false; + + var successful_returns = std.ArrayList(JSValue).init(globalThis.bunVM().allocator); + defer successful_returns.deinit(); + + var has_errors = false; + + // Check for a pass and collect info for error messages + for (0..calls_count) |i| { + const result = returns.getDirectIndex(globalThis, @truncate(i)); + + if (result.isObject()) { + const result_type = try result.get(globalThis, "type") orelse .js_undefined; + if (result_type.isString()) { + const type_str = try result_type.toBunString(globalThis); + defer type_str.deref(); + + if (type_str.eqlComptime("return")) { + const result_value = try result.get(globalThis, "value") orelse .js_undefined; + try successful_returns.append(result_value); + + // Check for pass condition only if not already passed + if (!pass) { + if (try result_value.jestDeepEquals(expected, globalThis)) { + pass = true; + } + } + } else if (type_str.eqlComptime("throw")) { + has_errors = true; + } + } + } + } + + if (pass != this.flags.not) { + return .js_undefined; + } + + // Handle failure + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + + const signature = comptime getSignature("toHaveReturnedWith", "expected", false); + + if (this.flags.not) { + const not_signature = comptime getSignature("toHaveReturnedWith", "expected", true); + return this.throw(globalThis, not_signature, "\n\n" ++ "Expected mock function not to have returned: {any}\n", .{expected.toFmt(&formatter)}); + } + + // No match was found. + const successful_returns_count = successful_returns.items.len; + + // Case: Only one successful return, no errors + if (calls_count == 1 and successful_returns_count == 1) { + const received = successful_returns.items[0]; + if (expected.isString() and received.isString()) { + const diff_format = DiffFormatter{ + .expected = expected, + .received = received, + .globalThis = globalThis, + .not = false, + }; + return this.throw(globalThis, signature, "\n\n{any}\n", .{diff_format}); + } + + return this.throw(globalThis, signature, "\n\nExpected: {any}\nReceived: {any}", .{ + expected.toFmt(&formatter), + received.toFmt(&formatter), + }); + } + + if (has_errors) { + // Case: Some calls errored + const list_formatter = AllCallsFormatter{ + .globalThis = globalThis, + .returns = returns, + .formatter = &formatter, + }; + const fmt = + \\Some calls errored: + \\ + \\ Expected: {any} + \\ Received: + \\{any} + \\ + \\ Number of returns: {d} + \\ Number of calls: {d} + ; + + switch (Output.enable_ansi_colors) { + inline else => |colors| { + return this.throw(globalThis, signature, Output.prettyFmt("\n\n" ++ fmt ++ "\n", colors), .{ + expected.toFmt(&formatter), + list_formatter, + successful_returns_count, + calls_count, + }); + }, + } + } else { + // Case: No errors, but no match (and multiple returns) + const list_formatter = SuccessfulReturnsFormatter{ + .globalThis = globalThis, + .successful_returns = &successful_returns, + .formatter = &formatter, + }; + const fmt = + \\ Expected: {any} + \\ Received: + \\{any} + \\ + \\ Number of returns: {d} + ; + + switch (Output.enable_ansi_colors) { + inline else => |colors| { + return this.throw(globalThis, signature, Output.prettyFmt("\n\n" ++ fmt ++ "\n", colors), .{ + expected.toFmt(&formatter), + list_formatter, + successful_returns_count, + }); + }, + } + } + } + + pub fn toHaveLastReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { + jsc.markBinding(@src()); + + const thisValue = callframe.this(); + defer this.postMatch(globalThis); + + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveBeenLastReturnedWith", "expected"); + + const expected = callframe.argumentsAsArray(1)[0]; + incrementExpectCallCounter(); + + const returns = try bun.cpp.JSMockFunction__getReturns(globalThis, value); + if (!returns.jsType().isArray()) { + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); + } + + const calls_count = @as(u32, @intCast(try returns.getLength(globalThis))); + var pass = false; + var last_return_value: JSValue = .js_undefined; + var last_call_threw = false; + var last_error_value: JSValue = .js_undefined; + + if (calls_count > 0) { + const last_result = returns.getDirectIndex(globalThis, calls_count - 1); + + if (last_result.isObject()) { + const result_type = try last_result.get(globalThis, "type") orelse .js_undefined; + if (result_type.isString()) { + const type_str = try result_type.toBunString(globalThis); + defer type_str.deref(); + + if (type_str.eqlComptime("return")) { + last_return_value = try last_result.get(globalThis, "value") orelse .js_undefined; + + if (try last_return_value.jestDeepEquals(expected, globalThis)) { + pass = true; + } + } else if (type_str.eqlComptime("throw")) { + last_call_threw = true; + last_error_value = try last_result.get(globalThis, "value") orelse .js_undefined; + } + } + } + } + + if (pass != this.flags.not) { + return .js_undefined; + } + + // Handle failure + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + + const signature = comptime getSignature("toHaveBeenLastReturnedWith", "expected", false); + + if (this.flags.not) { + return this.throw(globalThis, comptime getSignature("toHaveBeenLastReturnedWith", "expected", true), "\n\n" ++ "Expected mock function not to have last returned: {any}\n" ++ "But it did.\n", .{expected.toFmt(&formatter)}); + } + + if (calls_count == 0) { + return this.throw(globalThis, signature, "\n\n" ++ "The mock function was not called.", .{}); + } + + if (last_call_threw) { + return this.throw(globalThis, signature, "\n\n" ++ "The last call threw an error: {any}\n", .{last_error_value.toFmt(&formatter)}); + } + + // Diff if possible + if (expected.isString() and last_return_value.isString()) { + const diff_format = DiffFormatter{ .expected = expected, .received = last_return_value, .globalThis = globalThis, .not = false }; + return this.throw(globalThis, signature, "\n\n{any}\n", .{diff_format}); + } + + return this.throw(globalThis, signature, "\n\nExpected: {any}\nReceived: {any}", .{ expected.toFmt(&formatter), last_return_value.toFmt(&formatter) }); + } + pub fn toHaveNthReturnedWith(this: *Expect, globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { + jsc.markBinding(@src()); + const thisValue = callframe.this(); + defer this.postMatch(globalThis); + const value: JSValue = try this.getValue(globalThis, thisValue, "toHaveNthReturnedWith", "n, expected"); + + const nth_arg, const expected = callframe.argumentsAsArray(2); + + // Validate n is a number + if (!nth_arg.isAnyInt()) { + return globalThis.throwInvalidArguments("toHaveNthReturnedWith() first argument must be an integer", .{}); + } + + const n = nth_arg.toInt32(); + if (n <= 0) { + return globalThis.throwInvalidArguments("toHaveNthReturnedWith() n must be greater than 0", .{}); + } + + incrementExpectCallCounter(); + const returns = try bun.cpp.JSMockFunction__getReturns(globalThis, value); + if (!returns.jsType().isArray()) { + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + return globalThis.throw("Expected value must be a mock function: {any}", .{value.toFmt(&formatter)}); + } + + const calls_count = @as(u32, @intCast(try returns.getLength(globalThis))); + const index = @as(u32, @intCast(n - 1)); // Convert to 0-based index + + var pass = false; + var nth_return_value: JSValue = .js_undefined; + var nth_call_threw = false; + var nth_error_value: JSValue = .js_undefined; + var nth_call_exists = false; + + if (index < calls_count) { + nth_call_exists = true; + const nth_result = returns.getDirectIndex(globalThis, index); + if (nth_result.isObject()) { + const result_type = try nth_result.get(globalThis, "type") orelse .js_undefined; + if (result_type.isString()) { + const type_str = try result_type.toBunString(globalThis); + defer type_str.deref(); + if (type_str.eqlComptime("return")) { + nth_return_value = try nth_result.get(globalThis, "value") orelse .js_undefined; + if (try nth_return_value.jestDeepEquals(expected, globalThis)) { + pass = true; + } + } else if (type_str.eqlComptime("throw")) { + nth_call_threw = true; + nth_error_value = try nth_result.get(globalThis, "value") orelse .js_undefined; + } + } + } + } + + if (pass != this.flags.not) { + return .js_undefined; + } + + // Handle failure + var formatter = jsc.ConsoleObject.Formatter{ .globalThis = globalThis, .quote_strings = true }; + defer formatter.deinit(); + + const signature = comptime getSignature("toHaveNthReturnedWith", "n, expected", false); + + if (this.flags.not) { + return this.throw(globalThis, comptime getSignature("toHaveNthReturnedWith", "n, expected", true), "\n\n" ++ "Expected mock function not to have returned on call {d}: {any}\n" ++ "But it did.\n", .{ n, expected.toFmt(&formatter) }); + } + + if (!nth_call_exists) { + return this.throw(globalThis, signature, "\n\n" ++ "The mock function was called {d} time{s}, but call {d} was requested.\n", .{ calls_count, if (calls_count == 1) "" else "s", n }); + } + + if (nth_call_threw) { + return this.throw(globalThis, signature, "\n\n" ++ "Call {d} threw an error: {any}\n", .{ n, nth_error_value.toFmt(&formatter) }); + } + + // Diff if possible + if (expected.isString() and nth_return_value.isString()) { + const diff_format = DiffFormatter{ .expected = expected, .received = nth_return_value, .globalThis = globalThis, .not = false }; + return this.throw(globalThis, signature, "\n\nCall {d}:\n{any}\n", .{ n, diff_format }); + } + + return this.throw(globalThis, signature, "\n\nCall {d}:\nExpected: {any}\nReceived: {any}", .{ n, expected.toFmt(&formatter), nth_return_value.toFmt(&formatter) }); + } pub fn getStaticNot(globalThis: *JSGlobalObject, _: JSValue, _: JSValue) bun.JSError!JSValue { return ExpectStatic.create(globalThis, .{ .not = true }); @@ -5646,6 +6176,44 @@ pub const ExpectMatcherUtils = struct { } }; +pub const ExpectTypeOf = struct { + pub const js = jsc.Codegen.JSExpectTypeOf; + pub const toJS = js.toJS; + pub const fromJS = js.fromJS; + pub const fromJSDirect = js.fromJSDirect; + + pub fn finalize( + this: *ExpectTypeOf, + ) callconv(.C) void { + VirtualMachine.get().allocator.destroy(this); + } + + pub fn create(globalThis: *JSGlobalObject) bun.JSError!JSValue { + var expect = try globalThis.bunVM().allocator.create(ExpectTypeOf); + + const value = expect.toJS(globalThis); + value.ensureStillAlive(); + return value; + } + + pub fn fnOneArgumentReturnsVoid(_: *ExpectTypeOf, _: *JSGlobalObject, _: *CallFrame) bun.JSError!JSValue { + return .js_undefined; + } + pub fn fnOneArgumentReturnsExpectTypeOf(_: *ExpectTypeOf, globalThis: *JSGlobalObject, _: *CallFrame) bun.JSError!JSValue { + return create(globalThis); + } + pub fn getReturnsExpectTypeOf(_: *ExpectTypeOf, globalThis: *JSGlobalObject) bun.JSError!JSValue { + return create(globalThis); + } + + pub fn constructor(globalThis: *JSGlobalObject, _: *CallFrame) bun.JSError!*ExpectTypeOf { + return globalThis.throw("expectTypeOf() cannot be called with new", .{}); + } + pub fn call(globalThis: *JSGlobalObject, _: *CallFrame) bun.JSError!JSValue { + return create(globalThis); + } +}; + // Extract the matcher_fn from a JSCustomExpectMatcherFunction instance inline fn getCustomMatcherFn(thisValue: JSValue, globalThis: *JSGlobalObject) ?JSValue { const matcher_fn = Bun__JSWrappingFunction__getWrappedFunction(thisValue, globalThis); diff --git a/src/bun.js/test/jest.classes.ts b/src/bun.js/test/jest.classes.ts index 57b4273aba..14939cd2fd 100644 --- a/src/bun.js/test/jest.classes.ts +++ b/src/bun.js/test/jest.classes.ts @@ -630,4 +630,158 @@ export default [ }, }, }), + define({ + name: "ExpectTypeOf", + construct: true, + call: true, + finalize: true, + JSType: "0b11101110", + values: [], + configurable: false, + klass: {}, + proto: { + toBeAny: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeUnknown: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeNever: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeFunction: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeObject: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeArray: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeNumber: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeString: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeBoolean: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeVoid: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeSymbol: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeNull: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeUndefined: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeBigInt: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeCallableWith: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toBeConstructibleWith: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + extract: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + exclude: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + pick: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + omit: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + parameter: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + parameters: { + getter: "getReturnsExpectTypeOf", + }, + constructorParameters: { + getter: "getReturnsExpectTypeOf", + }, + thisParameter: { + getter: "getReturnsExpectTypeOf", + }, + instance: { + getter: "getReturnsExpectTypeOf", + }, + returns: { + getter: "getReturnsExpectTypeOf", + }, + resolves: { + getter: "getReturnsExpectTypeOf", + }, + items: { + getter: "getReturnsExpectTypeOf", + }, + guards: { + getter: "getReturnsExpectTypeOf", + }, + asserts: { + getter: "getReturnsExpectTypeOf", + }, + toMatchObjectType: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toExtend: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toEqualTypeOf: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toMatchTypeOf: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + toHaveProperty: { + fn: "fnOneArgumentReturnsVoid", + length: 1, + }, + + map: { + fn: "fnOneArgumentReturnsExpectTypeOf", + length: 1, + }, + not: { + getter: "getReturnsExpectTypeOf", + }, + branded: { + getter: "getReturnsExpectTypeOf", + }, + }, + }), ]; diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 2cd6868f3f..ffe7318c88 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -135,6 +135,10 @@ pub const TestRunner = struct { } } + pub fn hasTestFilter(this: *const TestRunner) bool { + return this.filter_regex != null; + } + pub fn setTimeout( this: *TestRunner, milliseconds: u32, @@ -439,6 +443,13 @@ pub const Jest = struct { Expect.js.getConstructor(globalObject), ); + // Add expectTypeOf function + module.put( + globalObject, + ZigString.static("expectTypeOf"), + ExpectTypeOf.js.getConstructor(globalObject), + ); + createMockObjects(globalObject, module); return module; @@ -462,6 +473,7 @@ pub const Jest = struct { module.put(globalObject, ZigString.static("mock"), mockFn); mockFn.put(globalObject, ZigString.static("module"), mockModuleFn); mockFn.put(globalObject, ZigString.static("restore"), restoreAllMocks); + mockFn.put(globalObject, ZigString.static("clearAllMocks"), clearAllMocks); const jest = JSValue.createEmptyObject(globalObject, 8); jest.put(globalObject, ZigString.static("fn"), mockFn); @@ -864,21 +876,28 @@ pub const DescribeScope = struct { line_number: u32 = 0, test_id_for_debugger: u32 = 0, + /// Does this DescribeScope or any of the children describe scopes have tests? + /// + /// If all tests were filtered out due to `-t`, then this will be false. + /// + /// .only has to be evaluated later.] + children_have_tests: bool = false, + fn isWithinOnlyScope(this: *const DescribeScope) bool { if (this.tag == .only) return true; - if (this.parent != null) return this.parent.?.isWithinOnlyScope(); + if (this.parent) |parent| return parent.isWithinOnlyScope(); return false; } fn isWithinSkipScope(this: *const DescribeScope) bool { if (this.tag == .skip) return true; - if (this.parent != null) return this.parent.?.isWithinSkipScope(); + if (this.parent) |parent| return parent.isWithinSkipScope(); return false; } fn isWithinTodoScope(this: *const DescribeScope) bool { if (this.tag == .todo) return true; - if (this.parent != null) return this.parent.?.isWithinTodoScope(); + if (this.parent) |parent| return parent.isWithinTodoScope(); return false; } @@ -886,7 +905,7 @@ pub const DescribeScope = struct { if (this.tag == .skip or this.tag == .todo) return false; if (Jest.runner.?.only and this.tag == .only) return true; - if (this.parent != null) return this.parent.?.shouldEvaluateScope(); + if (this.parent) |parent| return parent.shouldEvaluateScope(); return true; } @@ -1164,6 +1183,29 @@ pub const DescribeScope = struct { return .js_undefined; } + fn markChildrenHaveTests(this: *DescribeScope) void { + var parent: ?*DescribeScope = this; + while (parent) |scope| { + if (scope.children_have_tests) break; + scope.children_have_tests = true; + parent = scope.parent; + } + } + + // TODO: combine with shouldEvaluateScope() once we make beforeAll run with the first scheduled test in the scope. + fn shouldRunBeforeAllAndAfterAll(this: *const DescribeScope) bool { + if (this.children_have_tests) { + return true; + } + + if (Jest.runner.?.hasTestFilter()) { + // All tests in this scope were filtered out. + return false; + } + + return true; + } + pub fn runTests(this: *DescribeScope, globalObject: *JSGlobalObject) void { // Step 1. Initialize the test block globalObject.clearTerminationException(); @@ -1182,15 +1224,21 @@ pub const DescribeScope = struct { var i: TestRunner.Test.ID = 0; if (this.shouldEvaluateScope()) { - if (this.runCallback(globalObject, .beforeAll)) |err| { - _ = globalObject.bunVM().uncaughtException(globalObject, err, true); - while (i < end) { - Jest.runner.?.reportFailure(i + this.test_id_start, source.path.text, tests[i].label, 0, 0, this, tests[i].line_number); - i += 1; + // TODO: we need to delay running beforeAll until the first test + // actually runs instead of when we start scheduling tests. + // At this point, we don't properly know if we should run beforeAll scopes in cases like when `.only` is used. + if (this.shouldRunBeforeAllAndAfterAll()) { + if (this.runCallback(globalObject, .beforeAll)) |err| { + _ = globalObject.bunVM().uncaughtException(globalObject, err, true); + while (i < end) { + Jest.runner.?.reportFailure(i + this.test_id_start, source.path.text, tests[i].label, 0, 0, this, tests[i].line_number); + i += 1; + } + this.deinit(globalObject); + return; } - this.deinit(globalObject); - return; } + if (end == 0) { var runner = allocator.create(TestRunnerTask) catch unreachable; runner.* = .{ @@ -1242,7 +1290,8 @@ pub const DescribeScope = struct { return; } - if (this.shouldEvaluateScope()) { + if (this.shouldEvaluateScope() and this.shouldRunBeforeAllAndAfterAll()) { + // Run the afterAll callbacks, in reverse order // unless there were no tests for this scope if (this.execCallback(globalThis, .afterAll)) |err| { @@ -1646,7 +1695,6 @@ pub const TestRunnerTask = struct { test_.line_number, ), .fail_because_failing_test_passed => |count| { - Output.prettyErrorln(" ^ this test is marked as failing but it passed. Remove `.failing` if tested behavior now works", .{}); Jest.runner.?.reportFailure( test_id, this.source_file_path, @@ -1656,6 +1704,7 @@ pub const TestRunnerTask = struct { describe, test_.line_number, ); + Output.prettyErrorln(" ^ this test is marked as failing but it passed. Remove `.failing` if tested behavior now works", .{}); }, .fail_because_expected_has_assertions => { Output.err(error.AssertionError, "received 0 assertions, but expected at least one assertion to be called\n", .{}); @@ -1728,7 +1777,7 @@ pub const TestRunnerTask = struct { } } - describe.onTestComplete(globalThis, test_id, result == .skip or (!Jest.runner.?.test_options.run_todo and result == .todo)); + describe.onTestComplete(globalThis, test_id, result.isSkipped()); Jest.runner.?.runNextTest(); } @@ -1768,6 +1817,14 @@ pub const Result = union(TestRunner.Test.Status) { fail_because_expected_has_assertions: void, fail_because_expected_assertion_count: Counter, + pub fn isSkipped(this: *const Result) bool { + return switch (this.*) { + .skip, .skipped_because_label => true, + .todo => !Jest.runner.?.test_options.run_todo, + else => false, + }; + } + pub fn isFailure(this: *const Result) bool { return this.* == .fail or this.* == .timeout or this.* == .fail_because_expected_has_assertions or this.* == .fail_because_expected_assertion_count; } @@ -1960,6 +2017,10 @@ inline fn createScope( break :brk 0; }, }) catch unreachable; + + if (!is_skip) { + parent.markChildrenHaveTests(); + } } else { var scope = allocator.create(DescribeScope) catch unreachable; scope.* = .{ @@ -2429,6 +2490,7 @@ const Snapshots = @import("./snapshot.zig").Snapshots; const expect = @import("./expect.zig"); const Counter = expect.Counter; const Expect = expect.Expect; +const ExpectTypeOf = expect.ExpectTypeOf; const bun = @import("bun"); const ArrayIdentityContext = bun.ArrayIdentityContext; diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index 093fa17664..1b561dce7a 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -312,12 +312,12 @@ pub fn start( this.arena = try bun.MimallocArena.init(); var vm = try jsc.VirtualMachine.initWorker(this, .{ - .allocator = this.arena.?.allocator(), + .allocator = bun.default_allocator, .args = transform_options, .store_fd = this.store_fd, .graph = this.parent.standalone_module_graph, }); - vm.allocator = this.arena.?.allocator(); + vm.allocator = bun.default_allocator; vm.arena = &this.arena.?; var b = &vm.transpiler; diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index 4a1869ab53..b17d48043f 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -1464,6 +1464,15 @@ pub fn writeFileInternal(globalThis: *jsc.JSGlobalObject, path_or_blob_: *PathOr return writeFileWithSourceDestination(globalThis, &source_blob, &destination_blob, options); } +fn validateWritableBlob(globalThis: *jsc.JSGlobalObject, blob: *Blob) bun.JSError!void { + const store = blob.store orelse { + return globalThis.throw("Cannot write to a detached Blob", .{}); + }; + if (store.data == .bytes) { + return globalThis.throwInvalidArguments("Cannot write to a Blob backed by bytes, which are always read-only", .{}); + } +} + /// `Bun.write(destination, input, options?)` pub fn writeFile(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { const arguments = callframe.arguments(); @@ -1479,12 +1488,7 @@ pub fn writeFile(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun } // "Blob" must actually be a BunFile, not a webcore blob. if (path_or_blob == .blob) { - const store = path_or_blob.blob.store orelse { - return globalThis.throw("Cannot write to a detached Blob", .{}); - }; - if (store.data == .bytes) { - return globalThis.throwInvalidArguments("Cannot write to a Blob backed by bytes, which are always read-only", .{}); - } + try validateWritableBlob(globalThis, &path_or_blob.blob); } const data = args.nextEat() orelse { @@ -2224,6 +2228,8 @@ pub fn doWrite(this: *Blob, globalThis: *jsc.JSGlobalObject, callframe: *jsc.Cal var args = jsc.CallFrame.ArgumentsSlice.init(globalThis.bunVM(), arguments); defer args.deinit(); + try validateWritableBlob(globalThis, this); + const data = args.nextEat() orelse { return globalThis.throwInvalidArguments("blob.write(pathOrFdOrBlob, blob) expects a Blob-y thing to write", .{}); }; @@ -2275,13 +2281,14 @@ pub fn doUnlink(this: *Blob, globalThis: *jsc.JSGlobalObject, callframe: *jsc.Ca const arguments = callframe.arguments_old(1).slice(); var args = jsc.CallFrame.ArgumentsSlice.init(globalThis.bunVM(), arguments); defer args.deinit(); - const store = this.store orelse { - return jsc.JSPromise.resolvedPromiseValue(globalThis, globalThis.createInvalidArgs("Blob is detached", .{})); - }; + + try validateWritableBlob(globalThis, this); + + const store = this.store.?; return switch (store.data) { .s3 => |*s3| try s3.unlink(store, globalThis, args.nextEat()), .file => |file| file.unlink(globalThis), - else => jsc.JSPromise.resolvedPromiseValue(globalThis, globalThis.createInvalidArgs("Blob is read-only", .{})), + else => unreachable, // validateWritableBlob should have caught this }; } @@ -2569,9 +2576,9 @@ pub fn getWriter( return globalThis.throwInvalidArguments("options must be an object or undefined", .{}); } - var store = this.store orelse { - return globalThis.throwInvalidArguments("Blob is detached", .{}); - }; + try validateWritableBlob(globalThis, this); + + var store = this.store.?; if (this.isS3()) { const s3 = &this.store.?.data.s3; const path = s3.path(); @@ -2625,9 +2632,6 @@ pub fn getWriter( null, ); } - if (store.data != .file) { - return globalThis.throwInvalidArguments("Blob is read-only", .{}); - } if (Environment.isWindows) { const pathlike = store.data.file.pathlike; @@ -3010,6 +3014,33 @@ export fn Bun__Blob__getSizeForBindings(this: *Blob) callconv(.C) u64 { return this.getSizeForBindings(); } +export fn Blob__getDataPtr(value: jsc.JSValue) callconv(.C) ?*anyopaque { + const blob = Blob.fromJS(value) orelse return null; + const data = blob.sharedView(); + if (data.len == 0) return null; + return @constCast(data.ptr); +} + +export fn Blob__getSize(value: jsc.JSValue) callconv(.C) usize { + const blob = Blob.fromJS(value) orelse return 0; + const data = blob.sharedView(); + return data.len; +} + +export fn Blob__fromBytes(globalThis: *jsc.JSGlobalObject, ptr: ?[*]const u8, len: usize) callconv(.C) *Blob { + if (ptr == null or len == 0) { + const blob = new(initEmpty(globalThis)); + blob.allocator = bun.default_allocator; + return blob; + } + + const bytes = bun.default_allocator.dupe(u8, ptr.?[0..len]) catch bun.outOfMemory(); + const store = Store.init(bytes, bun.default_allocator); + var blob = initWithStore(store, globalThis); + blob.allocator = bun.default_allocator; + return new(blob); +} + pub fn getStat(this: *Blob, globalThis: *jsc.JSGlobalObject, callback: *jsc.CallFrame) bun.JSError!jsc.JSValue { const store = this.store orelse return .js_undefined; // TODO: make this async for files diff --git a/src/bun.js/webcore/Response.zig b/src/bun.js/webcore/Response.zig index 83b9013e65..2453ca8825 100644 --- a/src/bun.js/webcore/Response.zig +++ b/src/bun.js/webcore/Response.zig @@ -426,6 +426,17 @@ pub fn constructJSON( did_succeed = true; return bun.new(Response, response).toJS(globalThis); } + +fn validateRedirectStatusCode(globalThis: *jsc.JSGlobalObject, status_code: i32) bun.JSError!u16 { + switch (status_code) { + 301, 302, 303, 307, 308 => return @intCast(status_code), + else => { + const err = globalThis.createRangeErrorInstance("Failed to execute 'redirect' on 'Response': Invalid status code", .{}); + return globalThis.throwValue(err); + }, + } +} + pub fn constructRedirect( globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame, @@ -464,16 +475,17 @@ pub fn constructRedirect( if (args.nextEat()) |init| { if (init.isUndefinedOrNull()) {} else if (init.isNumber()) { - response.init.status_code = @as(u16, @intCast(@min(@max(0, init.toInt32()), std.math.maxInt(u16)))); - } else { - if (Response.Init.init(globalThis, init) catch |err| - if (err == error.JSError) return .zero else null) |_init| - { - response.init = _init; - response.init.status_code = 302; + response.init.status_code = try validateRedirectStatusCode(globalThis, init.toInt32()); + } else if (try Response.Init.init(globalThis, init)) |_init| { + errdefer response.init.deinit(bun.default_allocator); + response.init = _init; + + if (_init.status_code != 200) { + response.init.status_code = try validateRedirectStatusCode(globalThis, _init.status_code); } } } + if (globalThis.hasException()) { return .zero; } @@ -622,7 +634,13 @@ pub const Init = struct { if (!response_init.isCell()) return null; - if (response_init.jsType() == .DOMWrapper) { + const js_type = response_init.jsType(); + + if (!js_type.isObject()) { + return null; + } + + if (js_type == .DOMWrapper) { // fast path: it's a Request object or a Response object // we can skip calling JS getters if (response_init.asDirect(Request)) |req| { @@ -674,11 +692,11 @@ pub const Init = struct { return error.JSError; } - if (try response_init.fastGet(globalThis, .statusText)) |status_text| { + if (try response_init.getTruthy(globalThis, "statusText")) |status_text| { result.status_text = try bun.String.fromJS(status_text, globalThis); } - if (try response_init.fastGet(globalThis, .method)) |method_value| { + if (try response_init.getTruthy(globalThis, "method")) |method_value| { if (try Method.fromJS(globalThis, method_value)) |method| { result.method = method; } diff --git a/src/bun.js/webcore/ScriptExecutionContext.zig b/src/bun.js/webcore/ScriptExecutionContext.zig index 7cfc11f899..002a698ea3 100644 --- a/src/bun.js/webcore/ScriptExecutionContext.zig +++ b/src/bun.js/webcore/ScriptExecutionContext.zig @@ -15,6 +15,10 @@ pub const Identifier = enum(u32) { // concurrently because we expect these identifiers are mostly used by off-thread tasks return (self.globalObject() orelse return null).bunVMConcurrently(); } + + pub fn valid(self: Identifier) bool { + return self.globalObject() != null; + } }; const bun = @import("bun"); diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index e2b2e4e0f6..74a6791713 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -702,7 +702,7 @@ pub const Signal = struct { pub fn HTTPServerWritable(comptime ssl: bool) type { return struct { const UWSResponse = uws.NewApp(ssl).Response; - res: *UWSResponse, + res: ?*UWSResponse, buffer: bun.ByteList, pooled_buffer: ?*WebCore.ByteListPool.Node = null, offset: Blob.SizeType = 0, @@ -774,22 +774,26 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { bun.assert(!this.done); defer log("send: {d} bytes (backpressure: {any})", .{ buf.len, this.has_backpressure }); - if (this.requested_end and !this.res.state().isHttpWriteCalled()) { + const res = this.res orelse { + return false; + }; + + if (this.requested_end and !res.state().isHttpWriteCalled()) { this.handleFirstWriteIfNecessary(); - const success = this.res.tryEnd(buf, this.end_len, false); + const success = res.tryEnd(buf, this.end_len, false); if (success) { this.has_backpressure = false; this.handleWrote(this.end_len); - } else { + } else if (this.res != null) { this.has_backpressure = true; - this.res.onWritable(*@This(), onWritable, this); + res.onWritable(*@This(), onWritable, this); } return success; } // clean this so we know when its relevant or not this.end_len = 0; // we clear the onWritable handler so uWS can handle the backpressure for us - this.res.clearOnWritable(); + res.clearOnWritable(); this.handleFirstWriteIfNecessary(); // uWebSockets lacks a tryWrite() function // This means that backpressure will be handled by appending to an "infinite" memory buffer @@ -797,10 +801,10 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { // so in this scenario, we just append to the buffer // and report success if (this.requested_end) { - this.res.end(buf, false); + res.end(buf, false); this.has_backpressure = false; } else { - this.has_backpressure = this.res.write(buf) == .backpressure; + this.has_backpressure = res.write(buf) == .backpressure; } this.handleWrote(buf.len); return true; @@ -821,7 +825,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { // onWritable reset backpressure state to allow flushing this.has_backpressure = false; if (this.aborted) { - this.res.clearOnWritable(); this.signal.close(null); this.flushPromise(); this.finalize(); @@ -837,7 +840,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { // if we have nothing to write, we are done if (chunk.len == 0) { if (this.done) { - this.res.clearOnWritable(); this.signal.close(null); this.flushPromise(); this.finalize(); @@ -851,7 +853,9 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { total_written = chunk.len; if (this.requested_end) { - this.res.clearOnWritable(); + if (this.res) |res| { + res.clearOnWritable(); + } this.signal.close(null); this.flushPromise(); this.finalize(); @@ -875,7 +879,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { } pub fn start(this: *@This(), stream_start: Start) bun.sys.Maybe(void) { - if (this.aborted or this.res.hasResponded()) { + if (this.aborted or this.res == null or this.res.?.hasResponded()) { this.markDone(); this.signal.close(null); return .success; @@ -985,7 +989,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { return .success; } - if (this.res.hasResponded()) { + if (this.res == null or this.res.?.hasResponded()) { this.markDone(); this.signal.close(null); } @@ -1040,7 +1044,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { return .{ .owned = 0 }; } - if (this.res.hasResponded()) { + if (this.res == null or this.res.?.hasResponded()) { this.signal.close(null); this.markDone(); return .{ .done = {} }; @@ -1098,7 +1102,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { return .{ .owned = 0 }; } - if (this.res.hasResponded()) { + if (this.res == null or this.res.?.hasResponded()) { this.signal.close(null); this.markDone(); return .{ .done = {} }; @@ -1138,7 +1142,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { return .success; } - if (this.done or this.res.hasResponded()) { + if (this.done or this.res == null or this.res.?.hasResponded()) { this.signal.close(err); this.markDone(); this.finalize(); @@ -1167,7 +1171,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { return .{ .result = jsc.JSValue.jsNumber(0) }; } - if (this.done or this.res.hasResponded()) { + if (this.done or this.res == null or this.res.?.hasResponded()) { this.requested_end = true; this.signal.close(null); this.markDone(); @@ -1188,7 +1192,9 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { return .{ .result = value }; } } else { - this.res.end("", false); + if (this.res) |res| { + res.end("", false); + } } this.markDone(); @@ -1206,6 +1212,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { pub fn abort(this: *@This()) void { log("onAborted()", .{}); this.done = true; + this.res = null; this.unregisterAutoFlusher(); this.aborted = true; @@ -1222,8 +1229,9 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { } fn registerAutoFlusher(this: *@This()) void { + const res = this.res orelse return; // if we enqueue data we should reset the timeout - this.res.resetTimeout(); + res.resetTimeout(); if (!this.auto_flusher.registered) AutoFlusher.registerDeferredMicrotaskWithTypeUnchecked(@This(), this, this.globalThis.bunVM()); } @@ -1268,14 +1276,19 @@ pub fn HTTPServerWritable(comptime ssl: bool) type { log("finalize()", .{}); if (!this.done) { this.unregisterAutoFlusher(); - // make sure we detached the handlers before flushing inside the finalize function - this.res.clearOnWritable(); - this.res.clearAborted(); - this.res.clearOnData(); + if (this.res) |res| { + // make sure we detached the handlers before flushing inside the finalize function + res.clearOnWritable(); + res.clearAborted(); + res.clearOnData(); + } _ = this.flushNoWait(); this.done = true; - // is actually fine to call this if the socket is closed because of flushNoWait, the free will be defered by usockets - this.res.endStream(false); + + if (this.res) |res| { + // is actually fine to call this if the socket is closed because of flushNoWait, the free will be defered by usockets + res.endStream(false); + } } if (comptime !FeatureFlags.http_buffer_pooling) { diff --git a/src/bun.zig b/src/bun.zig index 5d93c3cfce..6af7762060 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -3533,6 +3533,10 @@ pub fn GenericIndex(backing_int: type, uid: anytype) type { pub inline fn unwrap(oi: Optional) ?Index { return if (oi == .none) null else @enumFromInt(@intFromEnum(oi)); } + + pub inline fn unwrapGet(oi: Optional) ?backing_int { + return if (oi == .none) null else @intFromEnum(oi); + } }; }; } @@ -3755,6 +3759,8 @@ pub const mach_port = if (Environment.isMac) std.c.mach_port_t else u32; pub const cpp = @import("cpp").bindings; +pub const asan = @import("./asan.zig"); + pub fn contains(item: anytype, list: *const std.ArrayListUnmanaged(@TypeOf(item))) bool { const T = @TypeOf(item); return switch (T) { @@ -3763,6 +3769,8 @@ pub fn contains(item: anytype, list: *const std.ArrayListUnmanaged(@TypeOf(item) }; } +pub const safety = @import("./safety.zig"); + const CopyFile = @import("./copy_file.zig"); const builtin = @import("builtin"); const std = @import("std"); diff --git a/src/bundler/LinkerContext.zig b/src/bundler/LinkerContext.zig index b3659c1fb6..083efafd20 100644 --- a/src/bundler/LinkerContext.zig +++ b/src/bundler/LinkerContext.zig @@ -22,8 +22,6 @@ pub const LinkerContext = struct { options: LinkerOptions = .{}, - ambiguous_result_pool: std.ArrayList(MatchImport) = undefined, - loop: EventLoop, /// string buffer containing pre-formatted unique keys @@ -147,18 +145,25 @@ pub const LinkerContext = struct { ); } - pub fn computeQuotedSourceContents(this: *LinkerContext, allocator: std.mem.Allocator, source_index: Index.Int) void { + pub fn computeQuotedSourceContents(this: *LinkerContext, _: std.mem.Allocator, source_index: Index.Int) void { debug("Computing Quoted Source Contents: {d}", .{source_index}); const loader: options.Loader = this.parse_graph.input_files.items(.loader)[source_index]; - const quoted_source_contents: *string = &this.graph.files.items(.quoted_source_contents)[source_index]; + const quoted_source_contents: *?[]u8 = &this.graph.files.items(.quoted_source_contents)[source_index]; if (!loader.canHaveSourceMap()) { - quoted_source_contents.* = ""; + if (quoted_source_contents.*) |slice| { + bun.default_allocator.free(slice); + quoted_source_contents.* = null; + } return; } const source: *const Logger.Source = &this.parse_graph.input_files.items(.source)[source_index]; - const mutable = MutableString.initEmpty(allocator); - quoted_source_contents.* = (js_printer.quoteForJSON(source.contents, mutable, false) catch bun.outOfMemory()).list.items; + var mutable = MutableString.initEmpty(bun.default_allocator); + js_printer.quoteForJSON(source.contents, &mutable, false) catch bun.outOfMemory(); + if (quoted_source_contents.*) |slice| { + bun.default_allocator.free(slice); + } + quoted_source_contents.* = mutable.slice(); } }; @@ -208,7 +213,6 @@ pub const LinkerContext = struct { try this.graph.load(entry_points, sources, server_component_boundaries, bundle.dynamic_import_entry_points.keys()); bundle.dynamic_import_entry_points.deinit(); - this.ambiguous_result_pool = std.ArrayList(MatchImport).init(this.allocator); var runtime_named_exports = &this.graph.ast.items(.named_exports)[Index.runtime.get()]; @@ -709,8 +713,8 @@ pub const LinkerContext = struct { } var quote_buf = try MutableString.init(worker.allocator, path.pretty.len + 2); - quote_buf = try js_printer.quoteForJSON(path.pretty, quote_buf, false); - j.pushStatic(quote_buf.list.items); // freed by arena + try js_printer.quoteForJSON(path.pretty, "e_buf, false); + j.pushStatic(quote_buf.slice()); // freed by arena } var next_mapping_source_index: i32 = 1; @@ -730,8 +734,8 @@ pub const LinkerContext = struct { var quote_buf = try MutableString.init(worker.allocator, path.pretty.len + ", ".len + 2); quote_buf.appendAssumeCapacity(", "); - quote_buf = try js_printer.quoteForJSON(path.pretty, quote_buf, false); - j.pushStatic(quote_buf.list.items); // freed by arena + try js_printer.quoteForJSON(path.pretty, "e_buf, false); + j.pushStatic(quote_buf.slice()); // freed by arena } } @@ -743,11 +747,11 @@ pub const LinkerContext = struct { const source_indices_for_contents = source_id_map.keys(); if (source_indices_for_contents.len > 0) { j.pushStatic("\n "); - j.pushStatic(quoted_source_map_contents[source_indices_for_contents[0]]); + j.pushStatic(quoted_source_map_contents[source_indices_for_contents[0]] orelse ""); for (source_indices_for_contents[1..]) |index| { j.pushStatic(",\n "); - j.pushStatic(quoted_source_map_contents[index]); + j.pushStatic(quoted_source_map_contents[index] orelse ""); } } j.pushStatic( @@ -2417,7 +2421,11 @@ pub const LinkerContext = struct { // 4. externals return .{ .joiner = j.* }; - var pieces = try std.ArrayList(OutputPiece).initCapacity(allocator, count); + var pieces = brk: { + errdefer j.deinit(); + break :brk try std.ArrayList(OutputPiece).initCapacity(allocator, count); + }; + errdefer pieces.deinit(); const complete_output = try j.done(allocator); var output = complete_output; diff --git a/src/bundler/LinkerGraph.zig b/src/bundler/LinkerGraph.zig index 45330f3d93..1fabfea6d0 100644 --- a/src/bundler/LinkerGraph.zig +++ b/src/bundler/LinkerGraph.zig @@ -429,7 +429,7 @@ pub const File = struct { entry_point_chunk_index: u32 = std.math.maxInt(u32), line_offset_table: bun.sourcemap.LineOffsetTable.List = .empty, - quoted_source_contents: string = "", + quoted_source_contents: ?[]u8 = null, pub fn isEntryPoint(this: *const File) bool { return this.entry_point_kind.isEntryPoint(); diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 195ad49cda..da5dacd792 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -3879,6 +3879,21 @@ pub const CompileResult = union(enum) { javascript: struct { source_index: Index.Int, result: js_printer.PrintResult, + + pub fn code(this: @This()) []const u8 { + return switch (this.result) { + .result => |result| result.code, + else => "", + }; + } + + pub fn allocator(this: @This()) std.mem.Allocator { + return switch (this.result) { + .result => |result| result.code_allocator, + // empty slice can be freed by any allocator + else => bun.default_allocator, + }; + } }, css: struct { result: bun.Maybe([]const u8, anyerror), @@ -3898,6 +3913,7 @@ pub const CompileResult = union(enum) { .result = js_printer.PrintResult{ .result = .{ .code = "", + .code_allocator = bun.default_allocator, }, }, }, @@ -3905,10 +3921,7 @@ pub const CompileResult = union(enum) { pub fn code(this: *const CompileResult) []const u8 { return switch (this.*) { - .javascript => |r| switch (r.result) { - .result => |r2| r2.code, - else => "", - }, + .javascript => |r| r.code(), .css => |*c| switch (c.result) { .result => |v| v, .err => "", @@ -3917,6 +3930,13 @@ pub const CompileResult = union(enum) { }; } + pub fn allocator(this: *const CompileResult) ?std.mem.Allocator { + return switch (this.*) { + .javascript => |js| js.allocator(), + else => null, + }; + } + pub fn sourceMapChunk(this: *const CompileResult) ?sourcemap.Chunk { return switch (this.*) { .javascript => |r| switch (r.result) { diff --git a/src/bundler/linker_context/generateChunksInParallel.zig b/src/bundler/linker_context/generateChunksInParallel.zig index e3d868f846..d4a33f371c 100644 --- a/src/bundler/linker_context/generateChunksInParallel.zig +++ b/src/bundler/linker_context/generateChunksInParallel.zig @@ -71,7 +71,7 @@ pub fn generateChunksInParallel( } { - const chunk_contexts = c.allocator.alloc(GenerateChunkCtx, chunks.len) catch unreachable; + const chunk_contexts = c.allocator.alloc(GenerateChunkCtx, chunks.len) catch bun.outOfMemory(); defer c.allocator.free(chunk_contexts); { @@ -102,7 +102,7 @@ pub fn generateChunksInParallel( debug(" START {d} compiling part ranges", .{total_count}); defer debug(" DONE {d} compiling part ranges", .{total_count}); - const combined_part_ranges = c.allocator.alloc(PendingPartRange, total_count) catch unreachable; + const combined_part_ranges = c.allocator.alloc(PendingPartRange, total_count) catch bun.outOfMemory(); defer c.allocator.free(combined_part_ranges); var remaining_part_ranges = combined_part_ranges; var batch = ThreadPoolLib.Batch{}; @@ -315,7 +315,7 @@ pub fn generateChunksInParallel( } const bundler = @as(*bun.bundle_v2.BundleV2, @fieldParentPtr("linker", c)); - var static_route_visitor = StaticRouteVisitor{ .c = c, .visited = bun.bit_set.AutoBitSet.initEmpty(bun.default_allocator, c.graph.files.len) catch unreachable }; + var static_route_visitor = StaticRouteVisitor{ .c = c, .visited = bun.bit_set.AutoBitSet.initEmpty(bun.default_allocator, c.graph.files.len) catch bun.outOfMemory() }; defer static_route_visitor.deinit(); if (root_path.len > 0) { @@ -354,7 +354,7 @@ pub fn generateChunksInParallel( switch (chunk.content.sourcemap(c.options.source_maps)) { .external, .linked => |tag| { const output_source_map = chunk.output_source_map.finalize(bun.default_allocator, code_result.shifts) catch @panic("Failed to allocate memory for external source map"); - var source_map_final_rel_path = bun.default_allocator.alloc(u8, chunk.final_rel_path.len + ".map".len) catch unreachable; + var source_map_final_rel_path = bun.default_allocator.alloc(u8, chunk.final_rel_path.len + ".map".len) catch bun.outOfMemory(); bun.copy(u8, source_map_final_rel_path, chunk.final_rel_path); bun.copy(u8, source_map_final_rel_path[chunk.final_rel_path.len..], ".map"); @@ -443,8 +443,8 @@ pub fn generateChunksInParallel( fdpath[chunk.final_rel_path.len..][0..bun.bytecode_extension.len].* = bun.bytecode_extension.*; break :brk options.OutputFile.init(.{ - .output_path = bun.default_allocator.dupe(u8, source_provider_url_str.slice()) catch unreachable, - .input_path = std.fmt.allocPrint(bun.default_allocator, "{s}" ++ bun.bytecode_extension, .{chunk.final_rel_path}) catch unreachable, + .output_path = bun.default_allocator.dupe(u8, source_provider_url_str.slice()) catch bun.outOfMemory(), + .input_path = std.fmt.allocPrint(bun.default_allocator, "{s}" ++ bun.bytecode_extension, .{chunk.final_rel_path}) catch bun.outOfMemory(), .input_loader = .js, .hash = if (chunk.template.placeholder.hash != null) bun.hash(bytecode) else null, .output_kind = .bytecode, @@ -462,7 +462,7 @@ pub fn generateChunksInParallel( // an error c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "Failed to generate bytecode for {s}", .{ chunk.final_rel_path, - }) catch unreachable; + }) catch bun.outOfMemory(); } } } diff --git a/src/bundler/linker_context/generateCodeForFileInChunkJS.zig b/src/bundler/linker_context/generateCodeForFileInChunkJS.zig index daa8a316dd..fd03de0e42 100644 --- a/src/bundler/linker_context/generateCodeForFileInChunkJS.zig +++ b/src/bundler/linker_context/generateCodeForFileInChunkJS.zig @@ -603,7 +603,8 @@ pub fn generateCodeForFileInChunkJS( if (out_stmts.len == 0) { return .{ .result = .{ - .code = &[_]u8{}, + .code = "", + .code_allocator = bun.default_allocator, .source_map = null, }, }; diff --git a/src/bundler/linker_context/generateCompileResultForJSChunk.zig b/src/bundler/linker_context/generateCompileResultForJSChunk.zig index 3996ab0ce8..cd0b13c8fc 100644 --- a/src/bundler/linker_context/generateCompileResultForJSChunk.zig +++ b/src/bundler/linker_context/generateCompileResultForJSChunk.zig @@ -64,8 +64,8 @@ fn generateCompileResultForJSChunkImpl(worker: *ThreadPool.Worker, c: *LinkerCon return .{ .javascript = .{ - .result = result, .source_index = part_range.source_index.get(), + .result = result, }, }; } diff --git a/src/bundler/linker_context/postProcessJSChunk.zig b/src/bundler/linker_context/postProcessJSChunk.zig index c8b696ceae..1d4b99a431 100644 --- a/src/bundler/linker_context/postProcessJSChunk.zig +++ b/src/bundler/linker_context/postProcessJSChunk.zig @@ -16,8 +16,8 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu defer arena.deinit(); // Also generate the cross-chunk binding code - var cross_chunk_prefix: []u8 = &.{}; - var cross_chunk_suffix: []u8 = &.{}; + var cross_chunk_prefix: js_printer.PrintResult = undefined; + var cross_chunk_suffix: js_printer.PrintResult = undefined; var runtime_scope: *Scope = &c.graph.ast.items(.module_scope)[c.graph.files.items(.input_file)[Index.runtime.value].get()]; var runtime_members = &runtime_scope.members; @@ -68,7 +68,7 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu }, chunk.renamer, false, - ).result.code; + ); cross_chunk_suffix = js_printer.print( worker.allocator, c.resolver.opts.target, @@ -81,7 +81,7 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu }, chunk.renamer, false, - ).result.code; + ); } // Generate the exports for the entry point, if there are any @@ -107,6 +107,7 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu .input = chunk.unique_key, }, }; + errdefer j.deinit(); const output_format = c.options.output_format; var line_offset: bun.sourcemap.LineColumnOffset.Optional = if (c.options.source_maps != .none) .{ .value = .{} } else .{ .null = {} }; @@ -119,7 +120,7 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu // Start with the hashbang if there is one. This must be done before the // banner because it only works if it's literally the first character. if (chunk.isEntryPoint()) { - const is_bun = ctx.c.graph.ast.items(.target)[chunk.entry_point.source_index].isBun(); + const is_bun = c.graph.ast.items(.target)[chunk.entry_point.source_index].isBun(); const hashbang = c.graph.ast.items(.hashbang)[chunk.entry_point.source_index]; if (hashbang.len > 0) { @@ -199,10 +200,10 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu else => {}, // no wrapper } - if (cross_chunk_prefix.len > 0) { + if (cross_chunk_prefix.result.code.len > 0) { newline_before_comment = true; - line_offset.advance(cross_chunk_prefix); - j.push(cross_chunk_prefix, bun.default_allocator); + line_offset.advance(cross_chunk_prefix.result.code); + j.push(cross_chunk_prefix.result.code, cross_chunk_prefix.result.code_allocator); } // Concatenate the generated JavaScript chunks together @@ -322,16 +323,16 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu // Stick the entry point tail at the end of the file. Deliberately don't // include any source mapping information for this because it's automatically // generated and doesn't correspond to a location in the input file. - j.push(tail_code, bun.default_allocator); + j.push(tail_code, entry_point_tail.allocator()); } // Put the cross-chunk suffix inside the IIFE - if (cross_chunk_suffix.len > 0) { + if (cross_chunk_suffix.result.code.len > 0) { if (newline_before_comment) { j.pushStatic("\n"); } - j.push(cross_chunk_suffix, bun.default_allocator); + j.push(cross_chunk_suffix.result.code, cross_chunk_suffix.result.code_allocator); } switch (output_format) { @@ -354,7 +355,7 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu { const input = c.parse_graph.input_files.items(.source)[chunk.entry_point.source_index].path; var buf = MutableString.initEmpty(worker.allocator); - js_printer.quoteForJSONBuffer(input.pretty, &buf, true) catch bun.outOfMemory(); + js_printer.quoteForJSON(input.pretty, &buf, true) catch bun.outOfMemory(); const str = buf.slice(); // worker.allocator is an arena j.pushStatic(str); line_offset.advance(str); @@ -815,6 +816,7 @@ pub fn generateEntryPointTailJS( .source_index = source_index, .result = .{ .result = .{ .code = "", + .code_allocator = bun.default_allocator, } }, }, }; diff --git a/src/cli/install.ps1 b/src/cli/install.ps1 index 39c49ac348..489209bea8 100644 --- a/src/cli/install.ps1 +++ b/src/cli/install.ps1 @@ -295,7 +295,7 @@ function Install-Bun { if (-not $NoPathUpdate) { $Path += $BunBin Write-Env -Key 'Path' -Value ($Path -join ';') - $env:PATH = $Path; + $env:PATH = $Path -join ';' } else { Write-Output "Skipping adding '${BunBin}' to the user's %PATH%`n" } diff --git a/src/cli/outdated_command.zig b/src/cli/outdated_command.zig index c642b75069..df801aab49 100644 --- a/src/cli/outdated_command.zig +++ b/src/cli/outdated_command.zig @@ -1,4 +1,10 @@ pub const OutdatedCommand = struct { + const OutdatedInfo = struct { + package_id: PackageID, + dep_id: DependencyID, + workspace_pkg_id: PackageID, + is_catalog: bool, + }; fn resolveCatalogDependency(manager: *PackageManager, dep: Install.Dependency) ?Install.Dependency.Version { return if (dep.version.tag == .catalog) blk: { const catalog_dep = manager.lockfile.catalogs.get( @@ -87,8 +93,13 @@ pub const OutdatedCommand = struct { try updateManifestsIfNecessary(manager, workspace_pkg_ids); try printOutdatedInfoTable(manager, workspace_pkg_ids, true, enable_ansi_colors); + } else if (manager.options.do.recursive) { + const all_workspaces = getAllWorkspaces(bun.default_allocator, manager) catch bun.outOfMemory(); + defer bun.default_allocator.free(all_workspaces); + + try updateManifestsIfNecessary(manager, all_workspaces); + try printOutdatedInfoTable(manager, all_workspaces, true, enable_ansi_colors); } else { - // just the current workspace const root_pkg_id = manager.root_package_id.get(manager.lockfile, manager.workspace_name_hash); if (root_pkg_id == invalid_package_id) return; @@ -118,6 +129,23 @@ pub const OutdatedCommand = struct { pub fn deinit(_: @This(), _: std.mem.Allocator) void {} }; + fn getAllWorkspaces( + allocator: std.mem.Allocator, + manager: *PackageManager, + ) OOM![]const PackageID { + const lockfile = manager.lockfile; + const packages = lockfile.packages.slice(); + const pkg_resolutions = packages.items(.resolution); + + var workspace_pkg_ids: std.ArrayListUnmanaged(PackageID) = .{}; + for (pkg_resolutions, 0..) |resolution, pkg_id| { + if (resolution.tag != .workspace and resolution.tag != .root) continue; + try workspace_pkg_ids.append(allocator, @intCast(pkg_id)); + } + + return workspace_pkg_ids.toOwnedSlice(allocator); + } + fn findMatchingWorkspaces( allocator: std.mem.Allocator, original_cwd: string, @@ -200,6 +228,108 @@ pub const OutdatedCommand = struct { return workspace_pkg_ids.items; } + const GroupedOutdatedInfo = struct { + package_id: PackageID, + dep_id: DependencyID, + workspace_pkg_id: PackageID, + is_catalog: bool, + grouped_workspace_names: ?[]const u8, + }; + + fn groupCatalogDependencies( + manager: *PackageManager, + outdated_items: []const OutdatedInfo, + _: []const PackageID, + ) !std.ArrayListUnmanaged(GroupedOutdatedInfo) { + const allocator = bun.default_allocator; + const lockfile = manager.lockfile; + const string_buf = lockfile.buffers.string_bytes.items; + const packages = lockfile.packages.slice(); + const pkg_names = packages.items(.name); + const dependencies = lockfile.buffers.dependencies.items; + + var result = std.ArrayListUnmanaged(GroupedOutdatedInfo){}; + + const CatalogKey = struct { + name_hash: u64, + catalog_name_hash: u64, + behavior: Behavior, + }; + var catalog_map = std.AutoHashMap(CatalogKey, std.ArrayList(PackageID)).init(allocator); + defer catalog_map.deinit(); + defer { + var iter = catalog_map.iterator(); + while (iter.next()) |entry| { + entry.value_ptr.deinit(); + } + } + for (outdated_items) |item| { + if (item.is_catalog) { + const dep = dependencies[item.dep_id]; + const name_hash = bun.hash(dep.name.slice(string_buf)); + const catalog_name = dep.version.value.catalog.slice(string_buf); + const catalog_name_hash = bun.hash(catalog_name); + const key = CatalogKey{ .name_hash = name_hash, .catalog_name_hash = catalog_name_hash, .behavior = dep.behavior }; + + const entry = try catalog_map.getOrPut(key); + if (!entry.found_existing) { + entry.value_ptr.* = std.ArrayList(PackageID).init(allocator); + } + try entry.value_ptr.append(item.workspace_pkg_id); + } else { + try result.append(allocator, .{ + .package_id = item.package_id, + .dep_id = item.dep_id, + .workspace_pkg_id = item.workspace_pkg_id, + .is_catalog = false, + .grouped_workspace_names = null, + }); + } + } + + // Second pass: add grouped catalog dependencies + for (outdated_items) |item| { + if (!item.is_catalog) continue; + + const dep = dependencies[item.dep_id]; + const name_hash = bun.hash(dep.name.slice(string_buf)); + const catalog_name = dep.version.value.catalog.slice(string_buf); + const catalog_name_hash = bun.hash(catalog_name); + const key = CatalogKey{ .name_hash = name_hash, .catalog_name_hash = catalog_name_hash, .behavior = dep.behavior }; + + const workspace_list = catalog_map.get(key) orelse continue; + + if (workspace_list.items[0] != item.workspace_pkg_id) continue; + var workspace_names = std.ArrayList(u8).init(allocator); + defer workspace_names.deinit(); + + const cat_name = dep.version.value.catalog.slice(string_buf); + if (cat_name.len > 0) { + try workspace_names.appendSlice("catalog:"); + try workspace_names.appendSlice(cat_name); + try workspace_names.appendSlice(" ("); + } else { + try workspace_names.appendSlice("catalog ("); + } + for (workspace_list.items, 0..) |workspace_id, i| { + if (i > 0) try workspace_names.appendSlice(", "); + const workspace_name = pkg_names[workspace_id].slice(string_buf); + try workspace_names.appendSlice(workspace_name); + } + try workspace_names.append(')'); + + try result.append(allocator, .{ + .package_id = item.package_id, + .dep_id = item.dep_id, + .workspace_pkg_id = item.workspace_pkg_id, + .is_catalog = true, + .grouped_workspace_names = try workspace_names.toOwnedSlice(), + }); + } + + return result; + } + fn printOutdatedInfoTable( manager: *PackageManager, workspace_pkg_ids: []const PackageID, @@ -261,7 +391,7 @@ pub const OutdatedCommand = struct { defer version_buf.deinit(); const version_writer = version_buf.writer(); - var outdated_ids: std.ArrayListUnmanaged(struct { package_id: PackageID, dep_id: DependencyID, workspace_pkg_id: PackageID }) = .{}; + var outdated_ids: std.ArrayListUnmanaged(OutdatedInfo) = .{}; defer outdated_ids.deinit(manager.allocator); for (workspace_pkg_ids) |workspace_pkg_id| { @@ -350,6 +480,7 @@ pub const OutdatedCommand = struct { .package_id = package_id, .dep_id = @intCast(dep_id), .workspace_pkg_id = workspace_pkg_id, + .is_catalog = dep.version.tag == .catalog, }, ) catch bun.outOfMemory(); } @@ -357,11 +488,23 @@ pub const OutdatedCommand = struct { if (outdated_ids.items.len == 0) return; + // Group catalog dependencies + var grouped_ids = try groupCatalogDependencies(manager, outdated_ids.items, workspace_pkg_ids); + defer grouped_ids.deinit(bun.default_allocator); + + // Recalculate max workspace length after grouping + var new_max_workspace: usize = max_workspace; + for (grouped_ids.items) |item| { + if (item.grouped_workspace_names) |names| { + if (names.len > new_max_workspace) new_max_workspace = names.len; + } + } + const package_column_inside_length = @max("Packages".len, max_name); const current_column_inside_length = @max("Current".len, max_current); const update_column_inside_length = @max("Update".len, max_update); const latest_column_inside_length = @max("Latest".len, max_latest); - const workspace_column_inside_length = @max("Workspace".len, max_workspace); + const workspace_column_inside_length = @max("Workspace".len, new_max_workspace); const column_left_pad = 1; const column_right_pad = 1; @@ -402,105 +545,106 @@ pub const OutdatedCommand = struct { table.printTopLineSeparator(); table.printColumnNames(); - for (workspace_pkg_ids) |workspace_pkg_id| { - inline for ([_]Behavior{ - .{ .prod = true }, - .{ .dev = true }, - .{ .peer = true }, - .{ .optional = true }, - }) |group_behavior| { - for (outdated_ids.items) |ids| { - if (workspace_pkg_id != ids.workspace_pkg_id) continue; - const package_id = ids.package_id; - const dep_id = ids.dep_id; + // Print grouped items sorted by behavior type + inline for ([_]Behavior{ + .{ .prod = true }, + .{ .dev = true }, + .{ .peer = true }, + .{ .optional = true }, + }) |group_behavior| { + for (grouped_ids.items) |item| { + const package_id = item.package_id; + const dep_id = item.dep_id; - const dep = dependencies[dep_id]; - if (!dep.behavior.includes(group_behavior)) continue; + const dep = dependencies[dep_id]; + if (!dep.behavior.includes(group_behavior)) continue; - const package_name = pkg_names[package_id].slice(string_buf); - const resolution = pkg_resolutions[package_id]; + const package_name = pkg_names[package_id].slice(string_buf); + const resolution = pkg_resolutions[package_id]; - var expired = false; - const manifest = manager.manifests.byNameAllowExpired( - manager, - manager.scopeForPackageName(package_name), - package_name, - &expired, - .load_from_memory_fallback_to_disk, - ) orelse continue; + var expired = false; + const manifest = manager.manifests.byNameAllowExpired( + manager, + manager.scopeForPackageName(package_name), + package_name, + &expired, + .load_from_memory_fallback_to_disk, + ) orelse continue; - const latest = manifest.findByDistTag("latest") orelse continue; - const resolved_version = resolveCatalogDependency(manager, dep) orelse continue; - const update = if (resolved_version.tag == .npm) - manifest.findBestVersion(resolved_version.value.npm.version, string_buf) orelse continue + const latest = manifest.findByDistTag("latest") orelse continue; + const resolved_version = resolveCatalogDependency(manager, dep) orelse continue; + const update = if (resolved_version.tag == .npm) + manifest.findBestVersion(resolved_version.value.npm.version, string_buf) orelse continue + else + manifest.findByDistTag(resolved_version.value.dist_tag.tag.slice(string_buf)) orelse continue; + + table.printLineSeparator(); + + { + // package name + const behavior_str = if (dep.behavior.dev) + " (dev)" + else if (dep.behavior.peer) + " (peer)" + else if (dep.behavior.optional) + " (optional)" else - manifest.findByDistTag(resolved_version.value.dist_tag.tag.slice(string_buf)) orelse continue; + ""; - table.printLineSeparator(); + Output.pretty("{s}", .{table.symbols.verticalEdge()}); + for (0..column_left_pad) |_| Output.pretty(" ", .{}); - { - // package name - const behavior_str = if (dep.behavior.dev) - " (dev)" - else if (dep.behavior.peer) - " (peer)" - else if (dep.behavior.optional) - " (optional)" - else - ""; - - Output.pretty("{s}", .{table.symbols.verticalEdge()}); - for (0..column_left_pad) |_| Output.pretty(" ", .{}); - - Output.pretty("{s}{s}", .{ package_name, behavior_str }); - for (package_name.len + behavior_str.len..package_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); - } - - { - // current version - Output.pretty("{s}", .{table.symbols.verticalEdge()}); - for (0..column_left_pad) |_| Output.pretty(" ", .{}); - - version_writer.print("{}", .{resolution.value.npm.version.fmt(string_buf)}) catch bun.outOfMemory(); - Output.pretty("{s}", .{version_buf.items}); - for (version_buf.items.len..current_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); - version_buf.clearRetainingCapacity(); - } - - { - // update version - Output.pretty("{s}", .{table.symbols.verticalEdge()}); - for (0..column_left_pad) |_| Output.pretty(" ", .{}); - - version_writer.print("{}", .{update.version.fmt(manifest.string_buf)}) catch bun.outOfMemory(); - Output.pretty("{s}", .{update.version.diffFmt(resolution.value.npm.version, manifest.string_buf, string_buf)}); - for (version_buf.items.len..update_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); - version_buf.clearRetainingCapacity(); - } - - { - // latest version - Output.pretty("{s}", .{table.symbols.verticalEdge()}); - for (0..column_left_pad) |_| Output.pretty(" ", .{}); - - version_writer.print("{}", .{latest.version.fmt(manifest.string_buf)}) catch bun.outOfMemory(); - Output.pretty("{s}", .{latest.version.diffFmt(resolution.value.npm.version, manifest.string_buf, string_buf)}); - for (version_buf.items.len..latest_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); - version_buf.clearRetainingCapacity(); - } - - if (was_filtered) { - Output.pretty("{s}", .{table.symbols.verticalEdge()}); - for (0..column_left_pad) |_| Output.pretty(" ", .{}); - - const workspace_name = pkg_names[workspace_pkg_id].slice(string_buf); - Output.pretty("{s}", .{workspace_name}); - - for (workspace_name.len..workspace_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); - } - - Output.pretty("{s}\n", .{table.symbols.verticalEdge()}); + Output.pretty("{s}{s}", .{ package_name, behavior_str }); + for (package_name.len + behavior_str.len..package_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); } + + { + // current version + Output.pretty("{s}", .{table.symbols.verticalEdge()}); + for (0..column_left_pad) |_| Output.pretty(" ", .{}); + + version_writer.print("{}", .{resolution.value.npm.version.fmt(string_buf)}) catch bun.outOfMemory(); + Output.pretty("{s}", .{version_buf.items}); + for (version_buf.items.len..current_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); + version_buf.clearRetainingCapacity(); + } + + { + // update version + Output.pretty("{s}", .{table.symbols.verticalEdge()}); + for (0..column_left_pad) |_| Output.pretty(" ", .{}); + + version_writer.print("{}", .{update.version.fmt(manifest.string_buf)}) catch bun.outOfMemory(); + Output.pretty("{s}", .{update.version.diffFmt(resolution.value.npm.version, manifest.string_buf, string_buf)}); + for (version_buf.items.len..update_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); + version_buf.clearRetainingCapacity(); + } + + { + // latest version + Output.pretty("{s}", .{table.symbols.verticalEdge()}); + for (0..column_left_pad) |_| Output.pretty(" ", .{}); + + version_writer.print("{}", .{latest.version.fmt(manifest.string_buf)}) catch bun.outOfMemory(); + Output.pretty("{s}", .{latest.version.diffFmt(resolution.value.npm.version, manifest.string_buf, string_buf)}); + for (version_buf.items.len..latest_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); + version_buf.clearRetainingCapacity(); + } + + if (was_filtered) { + Output.pretty("{s}", .{table.symbols.verticalEdge()}); + for (0..column_left_pad) |_| Output.pretty(" ", .{}); + + const workspace_name = if (item.grouped_workspace_names) |names| + names + else + pkg_names[item.workspace_pkg_id].slice(string_buf); + Output.pretty("{s}", .{workspace_name}); + + for (workspace_name.len..workspace_column_inside_length + column_right_pad) |_| Output.pretty(" ", .{}); + } + + Output.pretty("{s}\n", .{table.symbols.verticalEdge()}); } } diff --git a/src/cli/update_interactive_command.zig b/src/cli/update_interactive_command.zig index 8105fa4526..72733b06d5 100644 --- a/src/cli/update_interactive_command.zig +++ b/src/cli/update_interactive_command.zig @@ -3,11 +3,6 @@ pub const TerminalHyperlink = struct { text: []const u8, enabled: bool, - const Protocol = enum { - vscode, - cursor, - }; - pub fn new(link: []const u8, text: []const u8, enabled: bool) TerminalHyperlink { return TerminalHyperlink{ .link = link, @@ -43,7 +38,79 @@ pub const UpdateInteractiveCommand = struct { behavior: Behavior, use_latest: bool = false, manager: *PackageManager, + is_catalog: bool = false, + catalog_name: ?[]const u8 = null, }; + + const CatalogUpdate = struct { + version: []const u8, + workspace_path: []const u8, + }; + + // Common utility functions to reduce duplication + + fn buildPackageJsonPath(root_dir: []const u8, workspace_path: []const u8, path_buf: *bun.PathBuffer) []const u8 { + if (workspace_path.len > 0) { + return bun.path.joinAbsStringBuf( + root_dir, + path_buf, + &[_]string{ workspace_path, "package.json" }, + .auto, + ); + } else { + return bun.path.joinAbsStringBuf( + root_dir, + path_buf, + &[_]string{"package.json"}, + .auto, + ); + } + } + + // Helper to update a catalog entry at a specific path in the package.json AST + fn savePackageJson( + manager: *PackageManager, + package_json: anytype, // MapEntry from WorkspacePackageJSONCache + package_json_path: []const u8, + ) !void { + const preserve_trailing_newline = package_json.*.source.contents.len > 0 and + package_json.*.source.contents[package_json.*.source.contents.len - 1] == '\n'; + + var buffer_writer = JSPrinter.BufferWriter.init(manager.allocator); + try buffer_writer.buffer.list.ensureTotalCapacity(manager.allocator, package_json.*.source.contents.len + 1); + buffer_writer.append_newline = preserve_trailing_newline; + var package_json_writer = JSPrinter.BufferPrinter.init(buffer_writer); + + _ = JSPrinter.printJSON( + @TypeOf(&package_json_writer), + &package_json_writer, + package_json.*.root, + &package_json.*.source, + .{ + .indent = package_json.*.indentation, + .mangled_props = null, + }, + ) catch |err| { + Output.errGeneric("Failed to serialize package.json: {s}", .{@errorName(err)}); + return err; + }; + + const new_package_json_source = try manager.allocator.dupe(u8, package_json_writer.ctx.writtenWithoutTrailingZero()); + defer manager.allocator.free(new_package_json_source); + + // Write the updated package.json + const write_file = std.fs.cwd().createFile(package_json_path, .{}) catch |err| { + Output.errGeneric("Failed to write package.json at {s}: {s}", .{ package_json_path, @errorName(err) }); + return err; + }; + defer write_file.close(); + + write_file.writeAll(new_package_json_source) catch |err| { + Output.errGeneric("Failed to write package.json at {s}: {s}", .{ package_json_path, @errorName(err) }); + return err; + }; + } + fn resolveCatalogDependency(manager: *PackageManager, dep: Install.Dependency) ?Install.Dependency.Version { return if (dep.version.tag == .catalog) blk: { const catalog_dep = manager.lockfile.catalogs.get( @@ -76,90 +143,185 @@ pub const UpdateInteractiveCommand = struct { try updateInteractive(ctx, original_cwd, manager); } - fn updatePackages( + const PackageUpdate = struct { + name: []const u8, + target_version: []const u8, + dep_type: []const u8, // "dependencies", "devDependencies", etc. + workspace_path: []const u8, + original_version: []const u8, + package_id: PackageID, + }; + + fn updatePackageJsonFilesFromUpdates( manager: *PackageManager, - ctx: Command.Context, - updates: []UpdateRequest, - original_cwd: string, + updates: []const PackageUpdate, ) !void { - // This function follows the same pattern as updatePackageJSONAndInstallWithManagerWithUpdates - // from updatePackageJSONAndInstall.zig + // Group updates by workspace + var workspace_groups = bun.StringHashMap(std.ArrayList(PackageUpdate)).init(bun.default_allocator); + defer { + var it = workspace_groups.iterator(); + while (it.next()) |entry| { + entry.value_ptr.deinit(); + } + workspace_groups.deinit(); + } - // Load and parse the current package.json - var current_package_json = switch (manager.workspace_package_json_cache.getWithPath( - manager.allocator, - manager.log, - manager.original_package_json_path, - .{ .guess_indentation = true }, - )) { - .parse_err => |err| { - manager.log.print(Output.errorWriter()) catch {}; - Output.errGeneric("failed to parse package.json \"{s}\": {s}", .{ - manager.original_package_json_path, - @errorName(err), - }); - Global.crash(); - }, - .read_err => |err| { - Output.errGeneric("failed to read package.json \"{s}\": {s}", .{ - manager.original_package_json_path, - @errorName(err), - }); - Global.crash(); - }, - .entry => |entry| entry, - }; + // Group updates by workspace path + for (updates) |update| { + const result = try workspace_groups.getOrPut(update.workspace_path); + if (!result.found_existing) { + result.value_ptr.* = std.ArrayList(PackageUpdate).init(bun.default_allocator); + } + try result.value_ptr.append(update); + } - const current_package_json_indent = current_package_json.indentation; - const preserve_trailing_newline = current_package_json.source.contents.len > 0 and - current_package_json.source.contents[current_package_json.source.contents.len - 1] == '\n'; + // Process each workspace + var it = workspace_groups.iterator(); + while (it.next()) |entry| { + const workspace_path = entry.key_ptr.*; + const workspace_updates = entry.value_ptr.items; - // Set update mode - manager.to_update = true; - manager.update_requests = updates; + // Build the package.json path for this workspace + const root_dir = FileSystem.instance.top_level_dir; + var path_buf: bun.PathBuffer = undefined; + const package_json_path = buildPackageJsonPath(root_dir, workspace_path, &path_buf); - // Edit the package.json with all updates - // For interactive mode, we'll edit all as dependencies - // TODO: preserve original dependency types - var updates_mut = updates; - try PackageJSONEditor.edit( - manager, - &updates_mut, - ¤t_package_json.root, - "dependencies", - .{ - .exact_versions = manager.options.enable.exact_versions, - .before_install = true, - }, - ); + // Load and parse the package.json + var package_json = switch (manager.workspace_package_json_cache.getWithPath( + manager.allocator, + manager.log, + package_json_path, + .{ .guess_indentation = true }, + )) { + .parse_err => |err| { + Output.errGeneric("Failed to parse package.json at {s}: {s}", .{ package_json_path, @errorName(err) }); + continue; + }, + .read_err => |err| { + Output.errGeneric("Failed to read package.json at {s}: {s}", .{ package_json_path, @errorName(err) }); + continue; + }, + .entry => |package_entry| package_entry, + }; - // Serialize the updated package.json - var buffer_writer = JSPrinter.BufferWriter.init(manager.allocator); - try buffer_writer.buffer.list.ensureTotalCapacity(manager.allocator, current_package_json.source.contents.len + 1); - buffer_writer.append_newline = preserve_trailing_newline; - var package_json_writer = JSPrinter.BufferPrinter.init(buffer_writer); + var modified = false; - _ = JSPrinter.printJSON( - @TypeOf(&package_json_writer), - &package_json_writer, - current_package_json.root, - ¤t_package_json.source, - .{ - .indent = current_package_json_indent, - .mangled_props = null, - }, - ) catch |err| { - Output.prettyErrorln("package.json failed to write due to error {s}", .{@errorName(err)}); - Global.crash(); - }; + // Update each package in this workspace's package.json + for (workspace_updates) |update| { + // Find the package in the correct dependency section + if (package_json.root.data == .e_object) { + if (package_json.root.asProperty(update.dep_type)) |section_query| { + if (section_query.expr.data == .e_object) { + const dep_obj = §ion_query.expr.data.e_object; + if (section_query.expr.asProperty(update.name)) |version_query| { + if (version_query.expr.data == .e_string) { + // Get the original version to preserve prefix + const original_version = version_query.expr.data.e_string.data; - const new_package_json_source = try manager.allocator.dupe(u8, package_json_writer.ctx.writtenWithoutTrailingZero()); + // Preserve the version prefix from the original + const version_with_prefix = try preserveVersionPrefix(original_version, update.target_version, manager.allocator); - // Call installWithManager to perform the installation - try manager.installWithManager(ctx, new_package_json_source, original_cwd); + // Update the version using hash map put + const new_expr = try Expr.init( + E.String, + E.String{ .data = version_with_prefix }, + version_query.expr.loc, + ).clone(manager.allocator); + try dep_obj.*.put(manager.allocator, update.name, new_expr); + modified = true; + } + } + } + } + } + } + + // Write the updated package.json if modified + if (modified) { + try savePackageJson(manager, &package_json, package_json_path); + } + } + } + + fn updateCatalogDefinitions( + manager: *PackageManager, + catalog_updates: bun.StringHashMap(CatalogUpdate), + ) !void { + + // Group catalog updates by workspace path + var workspace_catalog_updates = bun.StringHashMap(std.ArrayList(CatalogUpdateRequest)).init(bun.default_allocator); + defer { + var it = workspace_catalog_updates.iterator(); + while (it.next()) |entry| { + entry.value_ptr.deinit(); + } + workspace_catalog_updates.deinit(); + } + + // Group updates by workspace + var catalog_it = catalog_updates.iterator(); + while (catalog_it.next()) |entry| { + const catalog_key = entry.key_ptr.*; + const update = entry.value_ptr.*; + + const result = try workspace_catalog_updates.getOrPut(update.workspace_path); + if (!result.found_existing) { + result.value_ptr.* = std.ArrayList(CatalogUpdateRequest).init(bun.default_allocator); + } + + // Parse catalog_key (format: "package_name" or "package_name:catalog_name") + const colon_index = std.mem.indexOf(u8, catalog_key, ":"); + const package_name = if (colon_index) |idx| catalog_key[0..idx] else catalog_key; + const catalog_name = if (colon_index) |idx| catalog_key[idx + 1 ..] else null; + + try result.value_ptr.append(.{ + .package_name = package_name, + .new_version = update.version, + .catalog_name = catalog_name, + }); + } + + // Update catalog definitions for each workspace + var workspace_it = workspace_catalog_updates.iterator(); + while (workspace_it.next()) |workspace_entry| { + const workspace_path = workspace_entry.key_ptr.*; + const updates_for_workspace = workspace_entry.value_ptr.*; + + // Build the package.json path for this workspace + const root_dir = FileSystem.instance.top_level_dir; + var path_buf: bun.PathBuffer = undefined; + const package_json_path = buildPackageJsonPath(root_dir, workspace_path, &path_buf); + + // Load and parse the package.json properly + var package_json = switch (manager.workspace_package_json_cache.getWithPath( + manager.allocator, + manager.log, + package_json_path, + .{ .guess_indentation = true }, + )) { + .parse_err => |err| { + Output.errGeneric("Failed to parse package.json at {s}: {s}", .{ package_json_path, @errorName(err) }); + continue; + }, + .read_err => |err| { + Output.errGeneric("Failed to read package.json at {s}: {s}", .{ package_json_path, @errorName(err) }); + continue; + }, + .entry => |entry| entry, + }; + + // Use the PackageJSONEditor to update catalogs + try editCatalogDefinitions(manager, updates_for_workspace.items, &package_json.root); + + // Save the updated package.json + try savePackageJson(manager, &package_json, package_json_path); + } } fn updateInteractive(ctx: Command.Context, original_cwd: string, manager: *PackageManager) !void { + // make the package manager things think we are actually in root dir + // _ = bun.sys.chdir(manager.root_dir.dir, manager.root_dir.dir); + const load_lockfile_result = manager.lockfile.loadFromCwd( manager, manager.allocator, @@ -201,151 +363,210 @@ pub const UpdateInteractiveCommand = struct { .ok => |ok| ok.lockfile, }; - switch (Output.enable_ansi_colors) { - inline else => |_| { - const workspace_pkg_ids = if (manager.options.filter_patterns.len > 0) blk: { - const filters = manager.options.filter_patterns; - break :blk findMatchingWorkspaces( - bun.default_allocator, - original_cwd, - manager, - filters, - ) catch bun.outOfMemory(); - } else blk: { - // just the current workspace - const root_pkg_id = manager.root_package_id.get(manager.lockfile, manager.workspace_name_hash); - if (root_pkg_id == invalid_package_id) return; - const ids = bun.default_allocator.alloc(PackageID, 1) catch bun.outOfMemory(); - ids[0] = root_pkg_id; - break :blk ids; - }; - defer bun.default_allocator.free(workspace_pkg_ids); + const workspace_pkg_ids = if (manager.options.filter_patterns.len > 0) blk: { + const filters = manager.options.filter_patterns; + break :blk findMatchingWorkspaces( + bun.default_allocator, + original_cwd, + manager, + filters, + ) catch bun.outOfMemory(); + } else if (manager.options.do.recursive) blk: { + break :blk getAllWorkspaces(bun.default_allocator, manager) catch bun.outOfMemory(); + } else blk: { + const root_pkg_id = manager.root_package_id.get(manager.lockfile, manager.workspace_name_hash); + if (root_pkg_id == invalid_package_id) return; - try OutdatedCommand.updateManifestsIfNecessary(manager, workspace_pkg_ids); + const ids = bun.default_allocator.alloc(PackageID, 1) catch bun.outOfMemory(); + ids[0] = root_pkg_id; + break :blk ids; + }; + defer bun.default_allocator.free(workspace_pkg_ids); - // Get outdated packages - const outdated_packages = try getOutdatedPackages(bun.default_allocator, manager, workspace_pkg_ids); - defer { - for (outdated_packages) |pkg| { - bun.default_allocator.free(pkg.name); - bun.default_allocator.free(pkg.current_version); - bun.default_allocator.free(pkg.latest_version); - bun.default_allocator.free(pkg.update_version); - bun.default_allocator.free(pkg.workspace_name); + try OutdatedCommand.updateManifestsIfNecessary(manager, workspace_pkg_ids); + + // Get outdated packages + const outdated_packages = try getOutdatedPackages(bun.default_allocator, manager, workspace_pkg_ids); + defer { + for (outdated_packages) |pkg| { + bun.default_allocator.free(pkg.name); + bun.default_allocator.free(pkg.current_version); + bun.default_allocator.free(pkg.latest_version); + bun.default_allocator.free(pkg.update_version); + bun.default_allocator.free(pkg.workspace_name); + } + bun.default_allocator.free(outdated_packages); + } + + if (outdated_packages.len == 0) { + // No packages need updating - just exit silently + Output.prettyln(" All packages are up to date!", .{}); + return; + } + + // Prompt user to select packages + const selected = try promptForUpdates(bun.default_allocator, outdated_packages); + defer bun.default_allocator.free(selected); + + // Create package specifier array from selected packages + // Group selected packages by workspace + var workspace_updates = bun.StringHashMap(std.ArrayList([]const u8)).init(bun.default_allocator); + defer { + var it = workspace_updates.iterator(); + while (it.next()) |entry| { + entry.value_ptr.deinit(); + } + workspace_updates.deinit(); + } + + // Track catalog updates separately (catalog_key -> {version, workspace_path}) + var catalog_updates = bun.StringHashMap(CatalogUpdate).init(bun.default_allocator); + defer { + var it = catalog_updates.iterator(); + while (it.next()) |entry| { + bun.default_allocator.free(entry.key_ptr.*); + bun.default_allocator.free(entry.value_ptr.*.version); + bun.default_allocator.free(entry.value_ptr.*.workspace_path); + } + catalog_updates.deinit(); + } + + // Collect all package updates with full information + var package_updates = std.ArrayList(PackageUpdate).init(bun.default_allocator); + defer package_updates.deinit(); + + // Process selected packages + for (outdated_packages, selected) |pkg, is_selected| { + if (!is_selected) continue; + + // Use latest version if requested + const target_version = if (pkg.use_latest) + pkg.latest_version + else + pkg.update_version; + + if (strings.eql(pkg.current_version, target_version)) { + continue; + } + + // For catalog dependencies, we need to collect them separately + // to update the catalog definitions in the root or workspace package.json + if (pkg.is_catalog) { + // Store catalog updates for later processing + const catalog_key = if (pkg.catalog_name) |catalog_name| + try std.fmt.allocPrint(bun.default_allocator, "{s}:{s}", .{ pkg.name, catalog_name }) + else + pkg.name; + + // For catalog dependencies, we always update the root package.json + // (or the workspace root where the catalog is defined) + const catalog_workspace_path = try bun.default_allocator.dupe(u8, ""); // Always root for now + + try catalog_updates.put(try bun.default_allocator.dupe(u8, catalog_key), .{ + .version = try bun.default_allocator.dupe(u8, target_version), + .workspace_path = catalog_workspace_path, + }); + continue; + } + + // Get the workspace path for this package + const workspace_resolution = manager.lockfile.packages.items(.resolution)[pkg.workspace_pkg_id]; + const workspace_path = if (workspace_resolution.tag == .workspace) + workspace_resolution.value.workspace.slice(manager.lockfile.buffers.string_bytes.items) + else + ""; // Root workspace + + // Add package update with full information + try package_updates.append(.{ + .name = try bun.default_allocator.dupe(u8, pkg.name), + .target_version = try bun.default_allocator.dupe(u8, target_version), + .dep_type = try bun.default_allocator.dupe(u8, pkg.dependency_type), + .workspace_path = try bun.default_allocator.dupe(u8, workspace_path), + .original_version = try bun.default_allocator.dupe(u8, pkg.current_version), + .package_id = pkg.package_id, + }); + } + + // Check if we have any updates + const has_package_updates = package_updates.items.len > 0; + const has_catalog_updates = catalog_updates.count() > 0; + + if (!has_package_updates and !has_catalog_updates) { + Output.prettyln("! No packages selected for update", .{}); + return; + } + + // Actually update the selected packages + if (has_package_updates or has_catalog_updates) { + if (manager.options.dry_run) { + Output.prettyln("\nDry run mode: showing what would be updated", .{}); + + // In dry-run mode, just show what would be updated without modifying files + for (package_updates.items) |update| { + const workspace_display = if (update.workspace_path.len > 0) update.workspace_path else "root"; + Output.prettyln("→ Would update {s} to {s} in {s} ({s})", .{ update.name, update.target_version, workspace_display, update.dep_type }); + } + + if (has_catalog_updates) { + var it = catalog_updates.iterator(); + while (it.next()) |entry| { + const catalog_key = entry.key_ptr.*; + const catalog_update = entry.value_ptr.*; + Output.prettyln("→ Would update catalog {s} to {s}", .{ catalog_key, catalog_update.version }); } - bun.default_allocator.free(outdated_packages); } - if (outdated_packages.len == 0) { - // Check if we're using --latest flag - const is_latest_mode = manager.options.do.update_to_latest; - - if (is_latest_mode) { - Output.prettyln(" All packages are up to date!", .{}); - } else { - // Count how many packages have newer versions available - var packages_with_newer_versions: usize = 0; - - // We need to check all packages for newer versions - for (workspace_pkg_ids) |workspace_pkg_id| { - const pkg_deps = manager.lockfile.packages.items(.dependencies)[workspace_pkg_id]; - for (pkg_deps.begin()..pkg_deps.end()) |dep_id| { - const package_id = manager.lockfile.buffers.resolutions.items[dep_id]; - if (package_id == invalid_package_id) continue; - const dep = manager.lockfile.buffers.dependencies.items[dep_id]; - const resolved_version = resolveCatalogDependency(manager, dep) orelse continue; - if (resolved_version.tag != .npm and resolved_version.tag != .dist_tag) continue; - const resolution = manager.lockfile.packages.items(.resolution)[package_id]; - if (resolution.tag != .npm) continue; - - const package_name = manager.lockfile.packages.items(.name)[package_id].slice(manager.lockfile.buffers.string_bytes.items); - - var expired = false; - const manifest = manager.manifests.byNameAllowExpired( - manager, - manager.scopeForPackageName(package_name), - package_name, - &expired, - .load_from_memory_fallback_to_disk, - ) orelse continue; - - const latest = manifest.findByDistTag("latest") orelse continue; - - // Check if current version is less than latest - if (resolution.value.npm.version.order(latest.version, manager.lockfile.buffers.string_bytes.items, manifest.string_buf) == .lt) { - packages_with_newer_versions += 1; - } - } - } - - if (packages_with_newer_versions > 0) { - Output.prettyln(" All packages are up to date!\n", .{}); - Output.prettyln("Excluded {d} package{s} with potentially breaking changes. Run `bun update -i --latest` to update", .{ packages_with_newer_versions, if (packages_with_newer_versions == 1) "" else "s" }); - } else { - Output.prettyln(" All packages are up to date!", .{}); - } - } - return; - } - - // Prompt user to select packages - const selected = try promptForUpdates(bun.default_allocator, outdated_packages); - defer bun.default_allocator.free(selected); - - // Create package specifier array from selected packages - var package_specifiers = std.ArrayList([]const u8).init(bun.default_allocator); - defer package_specifiers.deinit(); - - // Create a map to track dependency types for packages - var dep_types = bun.StringHashMap([]const u8).init(bun.default_allocator); - defer dep_types.deinit(); - - for (outdated_packages, selected) |pkg, is_selected| { - if (!is_selected) continue; - - try dep_types.put(pkg.name, pkg.dependency_type); - - // Use latest version if user selected it with 'l' key - const target_version = if (pkg.use_latest) pkg.latest_version else pkg.update_version; - - // Create a full package specifier string for UpdateRequest.parse - const package_specifier = try std.fmt.allocPrint(bun.default_allocator, "{s}@{s}", .{ pkg.name, target_version }); - - try package_specifiers.append(package_specifier); - } - - // dep_types will be freed when we exit this scope - - if (package_specifiers.items.len == 0) { - Output.prettyln("! No packages selected for update", .{}); - return; - } - - // Parse the package specifiers into UpdateRequests - var update_requests_array = UpdateRequest.Array{}; - const update_requests = UpdateRequest.parse( - bun.default_allocator, - manager, - manager.log, - package_specifiers.items, - &update_requests_array, - .update, - ); - - // Perform the update + Output.prettyln("\nDry run complete - no changes made", .{}); + } else { Output.prettyln("\nInstalling updates...", .{}); Output.flush(); - try updatePackages( - manager, - ctx, - update_requests, - original_cwd, - ); - }, + // Update catalog definitions first if needed + if (has_catalog_updates) { + try updateCatalogDefinitions(manager, catalog_updates); + } + + // Update all package.json files directly (fast!) + if (has_package_updates) { + try updatePackageJsonFilesFromUpdates(manager, package_updates.items); + } + + // Get the root package.json from cache (should be updated after our saves) + const package_json_contents = manager.root_package_json_file.readToEndAlloc(ctx.allocator, std.math.maxInt(usize)) catch |err| { + if (manager.options.log_level != .silent) { + Output.prettyErrorln("{s} reading package.json :(", .{@errorName(err)}); + Output.flush(); + } + return; + }; + manager.to_update = true; + + // Reset the timer to show actual install time instead of total command time + var install_ctx = ctx; + install_ctx.start_time = std.time.nanoTimestamp(); + + try PackageManager.installWithManager(manager, install_ctx, package_json_contents, manager.root_dir.dir); + } } } + fn getAllWorkspaces( + allocator: std.mem.Allocator, + manager: *PackageManager, + ) OOM![]const PackageID { + const lockfile = manager.lockfile; + const packages = lockfile.packages.slice(); + const pkg_resolutions = packages.items(.resolution); + + var workspace_pkg_ids: std.ArrayListUnmanaged(PackageID) = .{}; + for (pkg_resolutions, 0..) |resolution, pkg_id| { + if (resolution.tag != .workspace and resolution.tag != .root) continue; + try workspace_pkg_ids.append(allocator, @intCast(pkg_id)); + } + + return workspace_pkg_ids.toOwnedSlice(allocator); + } + fn findMatchingWorkspaces( allocator: std.mem.Allocator, original_cwd: string, @@ -428,6 +649,85 @@ pub const UpdateInteractiveCommand = struct { return workspace_pkg_ids.items; } + fn groupCatalogDependencies( + allocator: std.mem.Allocator, + packages: []OutdatedPackage, + ) ![]OutdatedPackage { + // Create a map to track catalog dependencies by name + var catalog_map = bun.StringHashMap(std.ArrayList(OutdatedPackage)).init(allocator); + defer catalog_map.deinit(); + defer { + var iter = catalog_map.iterator(); + while (iter.next()) |entry| { + entry.value_ptr.deinit(); + } + } + + var result = std.ArrayList(OutdatedPackage).init(allocator); + defer result.deinit(); + + // Group catalog dependencies + for (packages) |pkg| { + if (pkg.is_catalog) { + const entry = try catalog_map.getOrPut(pkg.name); + if (!entry.found_existing) { + entry.value_ptr.* = std.ArrayList(OutdatedPackage).init(allocator); + } + try entry.value_ptr.append(pkg); + } else { + try result.append(pkg); + } + } + + // Add grouped catalog dependencies + var iter = catalog_map.iterator(); + while (iter.next()) |entry| { + const catalog_packages = entry.value_ptr.items; + if (catalog_packages.len > 0) { + // Use the first package as the base, but combine workspace names + var first = catalog_packages[0]; + + // Build combined workspace name + var workspace_names = std.ArrayList(u8).init(allocator); + defer workspace_names.deinit(); + + if (catalog_packages.len > 0) { + if (catalog_packages[0].catalog_name) |catalog_name| { + try workspace_names.appendSlice("catalog:"); + try workspace_names.appendSlice(catalog_name); + } else { + try workspace_names.appendSlice("catalog"); + } + try workspace_names.appendSlice(" ("); + } else { + try workspace_names.appendSlice("catalog ("); + } + for (catalog_packages, 0..) |cat_pkg, i| { + if (i > 0) try workspace_names.appendSlice(", "); + try workspace_names.appendSlice(cat_pkg.workspace_name); + } + try workspace_names.append(')'); + + // Free the old workspace_name and replace with combined + allocator.free(first.workspace_name); + first.workspace_name = try workspace_names.toOwnedSlice(); + + try result.append(first); + + // Free the other catalog packages + for (catalog_packages[1..]) |cat_pkg| { + allocator.free(cat_pkg.name); + allocator.free(cat_pkg.current_version); + allocator.free(cat_pkg.latest_version); + allocator.free(cat_pkg.update_version); + allocator.free(cat_pkg.workspace_name); + } + } + } + + return result.toOwnedSlice(); + } + fn getOutdatedPackages( allocator: std.mem.Allocator, manager: *PackageManager, @@ -472,27 +772,30 @@ pub const UpdateInteractiveCommand = struct { const latest = manifest.findByDistTag("latest") orelse continue; - const update_version = if (manager.options.do.update_to_latest) - latest - else if (resolved_version.tag == .npm) - manifest.findBestVersion(resolved_version.value.npm.version, string_buf) orelse continue + // In interactive mode, show the constrained update version as "Target" + // but always include packages (don't filter out breaking changes) + const update_version = if (resolved_version.tag == .npm) + manifest.findBestVersion(resolved_version.value.npm.version, string_buf) orelse latest else - manifest.findByDistTag(resolved_version.value.dist_tag.tag.slice(string_buf)) orelse continue; + manifest.findByDistTag(resolved_version.value.dist_tag.tag.slice(string_buf)) orelse latest; - // Skip if current version is already the latest - if (resolution.value.npm.version.order(latest.version, string_buf, manifest.string_buf) != .lt) continue; - - // Skip if update version is the same as current version - // Note: Current version is in lockfile's string_buf, update version is in manifest's string_buf + // Skip only if both the constrained update AND the latest version are the same as current + // This ensures we show packages where latest is newer even if constrained update isn't const current_ver = resolution.value.npm.version; const update_ver = update_version.version; + const latest_ver = latest.version; - // Compare the actual version numbers - if (current_ver.major == update_ver.major and + const update_is_same = (current_ver.major == update_ver.major and current_ver.minor == update_ver.minor and current_ver.patch == update_ver.patch and - current_ver.tag.eql(update_ver.tag)) - { + current_ver.tag.eql(update_ver.tag)); + + const latest_is_same = (current_ver.major == latest_ver.major and + current_ver.minor == latest_ver.minor and + current_ver.patch == latest_ver.patch and + current_ver.tag.eql(latest_ver.tag)); + + if (update_is_same and latest_is_same) { continue; } @@ -520,6 +823,13 @@ pub const UpdateInteractiveCommand = struct { else ""; + const catalog_name_str = if (dep.version.tag == .catalog) + dep.version.value.catalog.slice(string_buf) + else + ""; + + const catalog_name: ?[]const u8 = if (catalog_name_str.len > 0) try allocator.dupe(u8, catalog_name_str) else null; + try outdated_packages.append(.{ .name = try allocator.dupe(u8, name_slice), .current_version = try allocator.dupe(u8, current_version_buf), @@ -532,14 +842,20 @@ pub const UpdateInteractiveCommand = struct { .workspace_name = try allocator.dupe(u8, workspace_name), .behavior = dep.behavior, .manager = manager, + .is_catalog = dep.version.tag == .catalog, + .catalog_name = catalog_name, + .use_latest = manager.options.do.update_to_latest, // default to --latest flag value }); } } const result = try outdated_packages.toOwnedSlice(); + // Group catalog dependencies + const grouped_result = try groupCatalogDependencies(allocator, result); + // Sort packages: dependencies first, then devDependencies, etc. - std.sort.pdq(OutdatedPackage, result, {}, struct { + std.sort.pdq(OutdatedPackage, grouped_result, {}, struct { fn lessThan(_: void, a: OutdatedPackage, b: OutdatedPackage) bool { // First sort by dependency type const a_priority = depTypePriority(a.dependency_type); @@ -559,7 +875,7 @@ pub const UpdateInteractiveCommand = struct { } }.lessThan); - return result; + return grouped_result; } const ColumnWidths = struct { @@ -567,6 +883,8 @@ pub const UpdateInteractiveCommand = struct { current: usize, target: usize, latest: usize, + workspace: usize, + show_workspace: bool, }; const MultiSelectState = struct { @@ -578,6 +896,8 @@ pub const UpdateInteractiveCommand = struct { max_current_len: usize = 0, max_update_len: usize = 0, max_latest_len: usize = 0, + max_workspace_len: usize = 0, + show_workspace: bool = false, }; fn calculateColumnWidths(packages: []OutdatedPackage) ColumnWidths { @@ -586,6 +906,8 @@ pub const UpdateInteractiveCommand = struct { var max_current_len: usize = "Current".len; var max_target_len: usize = "Target".len; var max_latest_len: usize = "Latest".len; + var max_workspace_len: usize = "Workspace".len; + var has_workspaces = false; for (packages) |pkg| { // Include dev tag length in max calculation @@ -602,6 +924,12 @@ pub const UpdateInteractiveCommand = struct { max_current_len = @max(max_current_len, pkg.current_version.len); max_target_len = @max(max_target_len, pkg.update_version.len); max_latest_len = @max(max_latest_len, pkg.latest_version.len); + max_workspace_len = @max(max_workspace_len, pkg.workspace_name.len); + + // Check if we have any non-empty workspace names + if (pkg.workspace_name.len > 0) { + has_workspaces = true; + } } // Use natural widths without any limits @@ -610,6 +938,8 @@ pub const UpdateInteractiveCommand = struct { .current = max_current_len, .target = max_target_len, .latest = max_latest_len, + .workspace = max_workspace_len, + .show_workspace = has_workspaces, }; } @@ -633,6 +963,8 @@ pub const UpdateInteractiveCommand = struct { .max_current_len = columns.current, .max_update_len = columns.target, .max_latest_len = columns.latest, + .max_workspace_len = columns.workspace, + .show_workspace = columns.show_workspace, }; // Set raw mode @@ -776,6 +1108,13 @@ pub const UpdateInteractiveCommand = struct { Output.print(" ", .{}); } Output.print("Latest", .{}); + if (state.show_workspace) { + j = 0; + while (j < state.max_latest_len - "Latest".len + 2) : (j += 1) { + Output.print(" ", .{}); + } + Output.print("Workspace", .{}); + } Output.print("\x1B[0K\n", .{}); displayed_lines += 1; current_dep_type = pkg.dependency_type; @@ -1023,6 +1362,17 @@ pub const UpdateInteractiveCommand = struct { } } + // Workspace column + if (state.show_workspace) { + const latest_width: usize = pkg.latest_version.len; + const latest_padding = if (latest_width >= state.max_latest_len) 0 else state.max_latest_len - latest_width; + j = 0; + while (j < latest_padding + 2) : (j += 1) { + Output.print(" ", .{}); + } + Output.pretty("{s}", .{pkg.workspace_name}); + } + Output.print("\x1B[0K\n", .{}); displayed_lines += 1; } @@ -1039,22 +1389,43 @@ pub const UpdateInteractiveCommand = struct { 3, 4 => return error.EndOfStream, // ctrl+c, ctrl+d ' ' => { state.selected[state.cursor] = !state.selected[state.cursor]; + // if the package only has a latest version, then we should toggle the latest version instead of update + if (strings.eql(state.packages[state.cursor].current_version, state.packages[state.cursor].update_version)) { + state.packages[state.cursor].use_latest = true; + } + state.toggle_all = false; // Don't move cursor on space - let user manually navigate }, 'a', 'A' => { @memset(state.selected, true); + state.toggle_all = true; // Mark that 'a' was used }, 'n', 'N' => { @memset(state.selected, false); + state.toggle_all = false; // Reset toggle_all mode }, 'i', 'I' => { // Invert selection for (state.selected) |*sel| { sel.* = !sel.*; } + state.toggle_all = false; // Reset toggle_all mode }, 'l', 'L' => { - state.packages[state.cursor].use_latest = !state.packages[state.cursor].use_latest; + // Only affect all packages if 'a' (select all) was used + // Otherwise, just toggle the current cursor package + if (state.toggle_all) { + // All packages were selected with 'a', so toggle latest for all selected packages + const new_latest_state = !state.packages[state.cursor].use_latest; + for (state.selected, state.packages) |sel, *pkg| { + if (sel) { + pkg.use_latest = new_latest_state; + } + } + } else { + // Individual selection mode, just toggle current cursor package + state.packages[state.cursor].use_latest = !state.packages[state.cursor].use_latest; + } }, 'j' => { if (state.cursor < state.packages.len - 1) { @@ -1062,6 +1433,7 @@ pub const UpdateInteractiveCommand = struct { } else { state.cursor = 0; } + state.toggle_all = false; }, 'k' => { if (state.cursor > 0) { @@ -1069,6 +1441,7 @@ pub const UpdateInteractiveCommand = struct { } else { state.cursor = state.packages.len - 1; } + state.toggle_all = false; }, 27 => { // escape sequence const seq = std.io.getStdIn().reader().readByte() catch continue; @@ -1092,8 +1465,11 @@ pub const UpdateInteractiveCommand = struct { else => {}, } } + state.toggle_all = false; + }, + else => { + state.toggle_all = false; }, - else => {}, } } } @@ -1103,6 +1479,185 @@ extern fn Bun__ttySetMode(fd: c_int, mode: c_int) c_int; const string = []const u8; +pub const CatalogUpdateRequest = struct { + package_name: string, + new_version: string, + catalog_name: ?string = null, +}; + +/// Edit catalog definitions in package.json +pub fn editCatalogDefinitions( + manager: *PackageManager, + updates: []CatalogUpdateRequest, + current_package_json: *Expr, +) !void { + // using data store is going to result in undefined memory issues as + // the store is cleared in some workspace situations. the solution + // is to always avoid the store + Expr.Disabler.disable(); + defer Expr.Disabler.enable(); + + const allocator = manager.allocator; + + for (updates) |update| { + if (update.catalog_name) |catalog_name| { + try updateNamedCatalog(allocator, current_package_json, catalog_name, update.package_name, update.new_version); + } else { + try updateDefaultCatalog(allocator, current_package_json, update.package_name, update.new_version); + } + } +} + +fn updateDefaultCatalog( + allocator: std.mem.Allocator, + package_json: *Expr, + package_name: string, + new_version: string, +) !void { + // Get or create the catalog object + // First check if catalog is under workspaces.catalog + var catalog_obj = brk: { + if (package_json.asProperty("workspaces")) |workspaces_query| { + if (workspaces_query.expr.data == .e_object) { + if (workspaces_query.expr.asProperty("catalog")) |catalog_query| { + if (catalog_query.expr.data == .e_object) + break :brk catalog_query.expr.data.e_object.*; + } + } + } + // Fallback to root-level catalog + if (package_json.asProperty("catalog")) |catalog_query| { + if (catalog_query.expr.data == .e_object) + break :brk catalog_query.expr.data.e_object.*; + } + break :brk E.Object{}; + }; + + // Get original version to preserve prefix if it exists + var version_with_prefix = new_version; + if (catalog_obj.get(package_name)) |existing_prop| { + if (existing_prop.data == .e_string) { + const original_version = existing_prop.data.e_string.data; + version_with_prefix = try preserveVersionPrefix(original_version, new_version, allocator); + } + } + + // Update or add the package version + const new_expr = Expr.allocate(allocator, E.String, E.String{ .data = version_with_prefix }, logger.Loc.Empty); + try catalog_obj.put(allocator, package_name, new_expr); + + // Check if we need to update under workspaces.catalog or root-level catalog + if (package_json.asProperty("workspaces")) |workspaces_query| { + if (workspaces_query.expr.data == .e_object) { + if (workspaces_query.expr.asProperty("catalog")) |_| { + // Update under workspaces.catalog + try workspaces_query.expr.data.e_object.put( + allocator, + "catalog", + Expr.allocate(allocator, E.Object, catalog_obj, logger.Loc.Empty), + ); + return; + } + } + } + + // Otherwise update at root level + try package_json.data.e_object.put( + allocator, + "catalog", + Expr.allocate(allocator, E.Object, catalog_obj, logger.Loc.Empty), + ); +} + +fn updateNamedCatalog( + allocator: std.mem.Allocator, + package_json: *Expr, + catalog_name: string, + package_name: string, + new_version: string, +) !void { + + // Get or create the catalogs object + // First check if catalogs is under workspaces.catalogs (newer structure) + var catalogs_obj = brk: { + if (package_json.asProperty("workspaces")) |workspaces_query| { + if (workspaces_query.expr.data == .e_object) { + if (workspaces_query.expr.asProperty("catalogs")) |catalogs_query| { + if (catalogs_query.expr.data == .e_object) + break :brk catalogs_query.expr.data.e_object.*; + } + } + } + // Fallback to root-level catalogs + if (package_json.asProperty("catalogs")) |catalogs_query| { + if (catalogs_query.expr.data == .e_object) + break :brk catalogs_query.expr.data.e_object.*; + } + break :brk E.Object{}; + }; + + // Get or create the specific catalog + var catalog_obj = brk: { + if (catalogs_obj.get(catalog_name)) |catalog_query| { + if (catalog_query.data == .e_object) + break :brk catalog_query.data.e_object.*; + } + break :brk E.Object{}; + }; + + // Get original version to preserve prefix if it exists + var version_with_prefix = new_version; + if (catalog_obj.get(package_name)) |existing_prop| { + if (existing_prop.data == .e_string) { + const original_version = existing_prop.data.e_string.data; + version_with_prefix = try preserveVersionPrefix(original_version, new_version, allocator); + } + } + + // Update or add the package version + const new_expr = Expr.allocate(allocator, E.String, E.String{ .data = version_with_prefix }, logger.Loc.Empty); + try catalog_obj.put(allocator, package_name, new_expr); + + // Update the catalog in catalogs object + try catalogs_obj.put( + allocator, + catalog_name, + Expr.allocate(allocator, E.Object, catalog_obj, logger.Loc.Empty), + ); + + // Check if we need to update under workspaces.catalogs or root-level catalogs + if (package_json.asProperty("workspaces")) |workspaces_query| { + if (workspaces_query.expr.data == .e_object) { + if (workspaces_query.expr.asProperty("catalogs")) |_| { + // Update under workspaces.catalogs + try workspaces_query.expr.data.e_object.put( + allocator, + "catalogs", + Expr.allocate(allocator, E.Object, catalogs_obj, logger.Loc.Empty), + ); + return; + } + } + } + + // Otherwise update at root level + try package_json.data.e_object.put( + allocator, + "catalogs", + Expr.allocate(allocator, E.Object, catalogs_obj, logger.Loc.Empty), + ); +} + +fn preserveVersionPrefix(original_version: string, new_version: string, allocator: std.mem.Allocator) !string { + if (original_version.len > 0) { + const first_char = original_version[0]; + if (first_char == '^' or first_char == '~' or first_char == '>' or first_char == '<' or first_char == '=') { + return try std.fmt.allocPrint(allocator, "{c}{s}", .{ first_char, new_version }); + } + } + return try allocator.dupe(u8, new_version); +} + const std = @import("std"); const bun = @import("bun"); @@ -1113,12 +1668,18 @@ const OOM = bun.OOM; const Output = bun.Output; const PathBuffer = bun.PathBuffer; const glob = bun.glob; +const logger = bun.logger; const path = bun.path; const strings = bun.strings; const FileSystem = bun.fs.FileSystem; const Semver = bun.Semver; const SlicedString = Semver.SlicedString; +const String = Semver.String; + +const JSAst = bun.ast; +const E = JSAst.E; +const Expr = JSAst.Expr; const Command = bun.cli.Command; const OutdatedCommand = bun.cli.OutdatedCommand; @@ -1131,5 +1692,4 @@ const Behavior = Install.Dependency.Behavior; const PackageManager = Install.PackageManager; const PackageJSONEditor = PackageManager.PackageJSONEditor; -const UpdateRequest = PackageManager.UpdateRequest; const WorkspaceFilter = PackageManager.WorkspaceFilter; diff --git a/src/codegen/cppbind.ts b/src/codegen/cppbind.ts index 91237006b4..46f17a46f7 100644 --- a/src/codegen/cppbind.ts +++ b/src/codegen/cppbind.ts @@ -1,8 +1,87 @@ -import { SyntaxNode } from "@lezer/common"; -import { parser as cppParser } from "@lezer/cpp"; -import { mkdir } from "fs/promises"; -import { join, relative } from "path"; -import { bannedTypes, sharedTypes, typeDeclarations } from "./shared-types"; +/* + +cppbind - C++ to Zig binding generator for Bun + +This tool automatically generates Zig bindings for C++ functions marked with [[ZIG_EXPORT(...)]] attributes. +It runs automatically when C++ files change during the build process. + +To run manually: + bun src/codegen/cppbind src build/debug/codegen + +## USAGE + +### Basic Export Tags + +1. **nothrow** - Function that never throws exceptions: + ```cpp + extern "C" [[ZIG_EXPORT(nothrow)]] void hello_world() { + printf("hello world\n"); + } + ``` + Zig usage: `bun.cpp.hello_world();` + +2. **zero_is_throw** - Function returns JSValue, where .zero indicates an exception: + ```cpp + extern "C" [[ZIG_EXPORT(zero_is_throw)]] JSValue create_object(JSGlobalObject* globalThis) { + auto scope = DECLARE_THROW_SCOPE(); + // ... + RETURN_IF_EXCEPTION(scope, {}); + return result; + } + ``` + Zig usage: `try bun.cpp.create_object(globalThis);` + +3. **check_slow** - Function that may throw, performs runtime exception checking: + ```cpp + extern "C" [[ZIG_EXPORT(check_slow)]] void process_data(JSGlobalObject* globalThis) { + auto scope = DECLARE_THROW_SCOPE(); + // ... + RETURN_IF_EXCEPTION(scope, ); + } + ``` + Zig usage: `try bun.cpp.process_data(globalThis);` + +### Parameters + +- **[[ZIG_NONNULL]]** - Mark pointer parameters as non-nullable: + ```cpp + [[ZIG_EXPORT(nothrow)]] void process([[ZIG_NONNULL]] JSGlobalObject* globalThis, + [[ZIG_NONNULL]] JSValue* values, + size_t count) { ... } + ``` + Generates: `pub extern fn process(globalThis: *jsc.JSGlobalObject, values: [*]const jsc.JSValue) void;` + +*/ + +const start = Date.now(); +let isInstalled = false; +try { + const grammarfile = await Bun.file("node_modules/@lezer/cpp/src/cpp.grammar").text(); + isInstalled = true; +} catch (e) {} +if (!isInstalled) { + if (process.argv.includes("--already-installed")) { + console.error("Lezer C++ grammar is not installed. Please run `bun install` to install it."); + process.exit(1); + } + const r = Bun.spawnSync([process.argv[0], "install", "--frozen-lockfile"], { + stdio: ["ignore", "pipe", "pipe"], + }); + if (r.exitCode !== 0) { + console.error(r.stdout.toString()); + console.error(r.stderr.toString()); + process.exit(r.exitCode ?? 1); + } + + const r2 = Bun.spawnSync([...process.argv, "--already-installed"], { stdio: ["inherit", "inherit", "inherit"] }); + process.exit(r2.exitCode ?? 1); +} + +type SyntaxNode = import("@lezer/common").SyntaxNode; +const { parser: cppParser } = await import("@lezer/cpp"); +const { mkdir } = await import("fs/promises"); +const { join, relative } = await import("path"); +const { bannedTypes, sharedTypes, typeDeclarations } = await import("./shared-types"); type Point = { line: number; @@ -31,11 +110,18 @@ type CppType = position: Srcloc; isConst: boolean; isMany: boolean; + isNonNull: boolean; } | { type: "named"; name: string; position: Srcloc; + } + | { + type: "fn"; + parameters: CppParameter[]; + returnType: CppType; + position: Srcloc; }; type PositionedError = { @@ -227,15 +313,41 @@ function processDeclarator( // Recursively peel off pointers if (declarator?.name === "PointerDeclarator") { if (!rootmostType) throwError(nodePosition(declarator, ctx), "no rootmost type provided to PointerDeclarator"); - const isConst = !!declarator.parent?.getChild("const"); + const isConst = !!declarator.parent?.getChild("const") || rootmostType.type === "fn"; + const parentAttributes = declarator.parent?.getChildren("Attribute") ?? []; + const isNonNull = parentAttributes.some(attr => text(attr.getChild("AttributeName")!, ctx) === "ZIG_NONNULL"); return processDeclarator(ctx, declarator, { type: "pointer", child: rootmostType, position: nodePosition(declarator, ctx), isConst, + isNonNull, isMany: false, }); + } else if (declarator?.name === "ReferenceDeclarator") { + throwError(nodePosition(declarator, ctx), "references are not allowed"); + } else if (declarator?.name === "FunctionDeclarator" && !declarator.getChild("Identifier")) { + const lhs = declarator.getChild("ParenthesizedDeclarator"); + const rhs = declarator.getChild("ParameterList"); + if (!lhs || !rhs) { + throwError( + nodePosition(declarator, ctx), + "FunctionDeclarator has neither Identifier nor ParenthesizedDeclarator:\n" + + prettyPrintLezerNode(declarator, ctx.sourceCode), + ); + } + const fnType: CppType = { + type: "fn", + parameters: [], + returnType: rootmostType, + position: nodePosition(declarator, ctx), + }; + for (const arg of rhs.getChildren("ParameterDeclaration")) { + const paramDeclarator = processDeclarator(ctx, arg); + fnType.parameters.push({ type: paramDeclarator.type, name: text(paramDeclarator.final, ctx) }); + } + return processDeclarator(ctx, lhs, fnType); } return { type: rootmostType, final: declarator }; @@ -260,9 +372,6 @@ function processFunction(ctx: ParseContext, node: SyntaxNode, tag: ExportTag): C const paramDeclarator = processDeclarator(ctx, parameter); const name = paramDeclarator.final; - if (name.name === "ReferenceDeclarator") { - throwError(nodePosition(name, ctx), "references are not allowed"); - } if (name.name !== "Identifier") { throwError(nodePosition(name, ctx), "parameter name is not an identifier: " + name.name); } @@ -305,16 +414,20 @@ for (const line of sharedTypesLines) { } const errorsForTypes: Map = new Map(); -function generateZigType(type: CppType, subLevel?: boolean) { +function generateZigType(type: CppType, parent: CppType | null) { if (type.type === "pointer") { - if (type.isMany && type.isConst) return `?[*]const ${generateZigType(type.child, true)}`; - if (type.isMany) return `?[*]${generateZigType(type.child, true)}`; - if (type.isConst) return `?*const ${generateZigType(type.child, true)}`; - return `?*${generateZigType(type.child, true)}`; + const optionalChar = type.isNonNull ? "" : "?"; + const ptrChar = type.isMany ? "[*]" : "*"; + const constChar = type.isConst ? "const " : ""; + return `${optionalChar}${ptrChar}${constChar}${generateZigType(type.child, type)}`; + } + if (type.type === "fn") { + return `fn(${type.parameters.map(p => formatZigName(p.name) + ": " + generateZigType(p.type, null)).join(", ")}) callconv(.C) ${generateZigType(type.returnType, null)}`; } if (type.type === "named" && type.name === "void") { - if (subLevel) return "anyopaque"; - return "void"; + if (parent?.type === "pointer") return "anyopaque"; + if (!parent) return "void"; + throwError(type.position, "void must have a pointer parent or no parent"); } if (type.type === "named") { const bannedType = bannedTypes[type.name]; @@ -350,7 +463,7 @@ function generateZigParameterList(parameters: CppParameter[], globalThisArg?: Cp if (p === globalThisArg) { return `${formatZigName(p.name)}: *jsc.JSGlobalObject`; } else { - return `${formatZigName(p.name)}: ${generateZigType(p.type, false)}`; + return `${formatZigName(p.name)}: ${generateZigType(p.type, null)}`; } }) .join(", "); @@ -526,7 +639,7 @@ function generateZigFn( resultSourceLinks: string[], cfg: Cfg, ): void { - const returnType = generateZigType(fn.returnType); + const returnType = generateZigType(fn.returnType, null); if (resultBindings.length) resultBindings.push(""); resultBindings.push(generateZigSourceComment(cfg, resultSourceLinks, fn)); if (fn.tag === "nothrow") { @@ -539,7 +652,7 @@ function generateZigFn( resultRaw.push(` extern fn ${formatZigName(fn.name)}(${generateZigParameterList(fn.parameters)}) ${returnType};`); let globalThisArg: CppParameter | undefined; for (const param of fn.parameters) { - const type = generateZigType(param.type); + const type = generateZigType(param.type, null); if (type === "?*jsc.JSGlobalObject") { globalThisArg = param; break; @@ -619,6 +732,18 @@ async function main() { const rootDir = args[0]; const dstDir = args[1]; if (!rootDir || !dstDir) { + console.error( + String.raw` + _ _ _ + | | (_) | | + ___ _ __ _ __ | |__ _ _ __ __| | + / __| '_ \| '_ \| '_ \| | '_ \ / _' | + | (__| |_) | |_) | |_) | | | | | (_| | + \___| .__/| .__/|_.__/|_|_| |_|\__,_| + | | | | + |_| |_| +`.slice(1), + ); console.error("Usage: bun src/codegen/cppbind "); process.exit(1); } @@ -676,14 +801,17 @@ async function main() { } const now = Date.now(); - const sin = Math.round(((Math.sin((now / 1000) * 1) + 1) / 2) * 24); + const sin = Math.round(((Math.sin((now / 1000) * 1) + 1) / 2) * 0); console.log( " ".repeat(sin) + (errors.length > 0 ? "✗" : "✓") + " cppbind.ts generated bindings to " + resultFilePath + - (errors.length > 0 ? " with errors" : ""), + (errors.length > 0 ? " with errors" : "") + + " in " + + (now - start) + + "ms", ); if (errors.length > 0) { process.exit(1); diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 5cb5038cb8..fcb59248a9 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -1868,11 +1868,50 @@ function generateZig( ...proto, }; - const externs = Object.entries({ + const gc_fields = Object.entries({ ...proto, ...Object.fromEntries((values || []).map(a => [a, { internal: true }])), - }) - .filter(([name, { cache, internal }]) => (cache && typeof cache !== "string") || internal) + }).filter(([name, { cache, internal }]) => (cache && typeof cache !== "string") || internal); + + const cached_values_string = + gc_fields.length > 0 + ? ` + pub const gc = enum (u8) { + ${gc_fields.map(([name]) => `${name},`).join("\n")} + + pub fn get(comptime field: gc, thisValue: jsc.JSValue) ?jsc.JSValue { + const value = switch (field) { + ${gc_fields + .map(([name]) => ` .${name} => ${protoSymbolName(typeName, name)}GetCachedValue(thisValue),`) + .join("\n ")} + }; + + if (value == .zero) { + return null; + } + + return value; + } + + pub fn clear(comptime field: gc, thisValue: jsc.JSValue, globalObject: *jsc.JSGlobalObject) void { + field.set(thisValue, globalObject, .zero); + } + + pub fn set(comptime field: gc, thisValue: jsc.JSValue, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void { + switch (field) { + ${gc_fields + .map( + ([name]) => + ` .${name} => ${protoSymbolName(typeName, name)}SetCachedValue(thisValue, globalObject, value),`, + ) + .join("\n")} + } + } + }; + ` + : ""; + + const externs = gc_fields .map( ([name]) => `extern fn ${protoSymbolName(typeName, name)}SetCachedValue(jsc.JSValue, *jsc.JSGlobalObject, jsc.JSValue) callconv(jsc.conv) void; @@ -2191,6 +2230,7 @@ pub const ${className(typeName)} = struct { } ${externs} + ${cached_values_string} ${ !noConstructor @@ -2620,7 +2660,7 @@ fn log_zig_getter(typename: []const u8, property_name: []const u8) callconv(bun. fn log_zig_setter(typename: []const u8, property_name: []const u8, value: jsc.JSValue) callconv(bun.callconv_inline) void { if (comptime Environment.enable_logs) { - zig("set {s}.{s} = {}", .{typename, property_name, value}); + zig("set {s}.{s} = {?s}", .{typename, property_name, bun.tagName(jsc.JSValue, value)}); } } diff --git a/src/codegen/shared-types.ts b/src/codegen/shared-types.ts index 0307c9c322..2c05247b9c 100644 --- a/src/codegen/shared-types.ts +++ b/src/codegen/shared-types.ts @@ -38,6 +38,7 @@ export const sharedTypes: Record = { // Common Bun types "BunString": "bun.String", "JSC::EncodedJSValue": "jsc.JSValue", + "EncodedJSValue": "jsc.JSValue", "JSC::JSGlobalObject": "jsc.JSGlobalObject", "ZigException": "jsc.ZigException", "Inspector::InspectorHTTPServerAgent": "HTTPServerAgent.InspectorHTTPServerAgent", diff --git a/src/collections/baby_list.zig b/src/collections/baby_list.zig index 2046848e07..5e0f6d1b76 100644 --- a/src/collections/baby_list.zig +++ b/src/collections/baby_list.zig @@ -6,7 +6,7 @@ pub fn BabyList(comptime Type: type) type { ptr: [*]Type = &[_]Type{}, len: u32 = 0, cap: u32 = 0, - alloc_ptr: CheckedAllocPtr = .{}, + alloc_ptr: bun.safety.AllocPtr = .{}, pub const Elem = Type; pub fn parse(input: *bun.css.Parser) bun.css.Result(ListType) { @@ -479,7 +479,6 @@ pub fn OffsetList(comptime Type: type) type { } const std = @import("std"); -const CheckedAllocPtr = @import("./safety.zig").AllocPtr; const bun = @import("bun"); const Environment = bun.Environment; diff --git a/src/collections/hive_array.zig b/src/collections/hive_array.zig index 47164bf011..9386e4a1ee 100644 --- a/src/collections/hive_array.zig +++ b/src/collections/hive_array.zig @@ -29,21 +29,20 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { pub fn get(self: *Self) ?*T { const index = self.used.findFirstUnset() orelse return null; self.used.set(index); - return &self.buffer[index]; + const ret = &self.buffer[index]; + bun.asan.unpoison(@ptrCast(ret), @sizeOf(T)); + return ret; } pub fn at(self: *Self, index: u16) *T { assert(index < capacity); - return &self.buffer[index]; - } - - pub fn claim(self: *Self, index: u16) void { - assert(index < capacity); - assert(!self.used.isSet(index)); - self.used.set(index); + const ret = &self.buffer[index]; + bun.asan.assertUnpoisoned(@ptrCast(ret)); + return ret; } pub fn indexOf(self: *const Self, value: *const T) ?u32 { + bun.asan.assertUnpoisoned(@ptrCast(value)); const start = &self.buffer; const end = @as([*]const T, @ptrCast(start)) + capacity; if (!(@intFromPtr(value) >= @intFromPtr(start) and @intFromPtr(value) < @intFromPtr(end))) @@ -57,6 +56,7 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { } pub fn in(self: *const Self, value: *const T) bool { + bun.asan.assertUnpoisoned(@ptrCast(value)); const start = &self.buffer; const end = @as([*]const T, @ptrCast(start)) + capacity; return (@intFromPtr(value) >= @intFromPtr(start) and @intFromPtr(value) < @intFromPtr(end)); @@ -69,6 +69,7 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { assert(&self.buffer[index] == value); value.* = undefined; + bun.asan.poison(value, @sizeOf(T)); self.used.unset(index); return true; @@ -88,6 +89,11 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { } pub fn get(self: *This) *T { + const value = getImpl(self); + return value; + } + + fn getImpl(self: *This) *T { if (comptime capacity > 0) { if (self.hive.get()) |value| { return value; diff --git a/src/collections/multi_array_list.zig b/src/collections/multi_array_list.zig index d165ed4e36..8063252312 100644 --- a/src/collections/multi_array_list.zig +++ b/src/collections/multi_array_list.zig @@ -1,3 +1,10 @@ +/// Copy of `std.MultiArrayList` with the following changes: +/// +/// * Added `zero` method to zero-initialize memory. +/// * Added `memoryCost` method, which returns the memory usage in bytes. +/// +/// Synchronized with std as of Zig 0.14.1. +/// /// A MultiArrayList stores a list of a struct or tagged union type. /// Instead of storing a single list of items, MultiArrayList /// stores separate lists for each field of the struct or @@ -14,7 +21,7 @@ pub fn MultiArrayList(comptime T: type) type { bytes: [*]align(@alignOf(T)) u8 = undefined, len: usize = 0, capacity: usize = 0, - alloc_ptr: CheckedAllocPtr = .{}, + alloc_ptr: bun.safety.AllocPtr = .{}, pub const empty: Self = .{ .bytes = undefined, @@ -163,6 +170,7 @@ pub fn MultiArrayList(comptime T: type) type { return lhs.alignment > rhs.alignment; } }; + @setEvalBranchQuota(3 * fields.len * std.math.log2(fields.len)); mem.sort(Data, &data, {}, Sort.lessThan); var sizes_bytes: [fields.len]usize = undefined; var field_indexes: [fields.len]usize = undefined; @@ -177,10 +185,10 @@ pub fn MultiArrayList(comptime T: type) type { }; /// Release all allocated memory. - pub fn deinit(self: *const Self, gpa: Allocator) void { + pub fn deinit(self: *Self, gpa: Allocator) void { self.alloc_ptr.assertEq(gpa); gpa.free(self.allocatedBytes()); - @constCast(self).* = undefined; + self.* = undefined; } /// The caller owns the returned memory. Empties this MultiArrayList. @@ -259,7 +267,7 @@ pub fn MultiArrayList(comptime T: type) type { return index; } - /// Remove and return the last element from the list, or return null if list is empty. + /// Remove and return the last element from the list, or return `null` if list is empty. /// Invalidates pointers to fields of the removed element. pub fn pop(self: *Self) ?T { if (self.len == 0) return null; @@ -278,11 +286,6 @@ pub fn MultiArrayList(comptime T: type) type { self.insertAssumeCapacity(index, elem); } - /// Invalidates all element pointers. - pub fn clearRetainingCapacity(this: *Self) void { - this.len = 0; - } - /// Inserts an item into an ordered list which has room for it. /// Shifts all elements after and including the specified index /// back by one and sets the given index to the specified element. @@ -307,11 +310,11 @@ pub fn MultiArrayList(comptime T: type) type { } } - pub fn appendListAssumeCapacity(this: *Self, other: Self) void { - const offset = this.len; - this.len += other.len; + pub fn appendListAssumeCapacity(self: *Self, other: Self) void { + const offset = self.len; + self.len += other.len; const other_slice = other.slice(); - const this_slice = this.slice(); + const this_slice = self.slice(); inline for (fields, 0..) |field_info, i| { if (@sizeOf(field_info.type) != 0) { const field = @as(Field, @enumFromInt(i)); @@ -416,20 +419,34 @@ pub fn MultiArrayList(comptime T: type) type { self.len = new_len; } + /// Invalidates all element pointers. + pub fn clearRetainingCapacity(self: *Self) void { + self.len = 0; + } + /// Modify the array so that it can hold at least `new_capacity` items. /// Implements super-linear growth to achieve amortized O(1) append operations. - /// Invalidates pointers if additional memory is needed. - pub fn ensureTotalCapacity(self: *Self, gpa: Allocator, new_capacity: usize) !void { - self.alloc_ptr.set(gpa); - var better_capacity = self.capacity; - if (better_capacity >= new_capacity) return; + /// Invalidates element pointers if additional memory is needed. + pub fn ensureTotalCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { + if (self.capacity >= new_capacity) return; + return self.setCapacity(gpa, growCapacity(self.capacity, new_capacity)); + } + const init_capacity = init: { + var max = 1; + for (fields) |field| max = @as(comptime_int, @max(max, @sizeOf(field.type))); + break :init @as(comptime_int, @max(1, std.atomic.cache_line / max)); + }; + + /// Called when memory growth is necessary. Returns a capacity larger than + /// minimum that grows super-linearly. + fn growCapacity(current: usize, minimum: usize) usize { + var new = current; while (true) { - better_capacity += better_capacity / 2 + 8; - if (better_capacity >= new_capacity) break; + new +|= new / 2 + init_capacity; + if (new >= minimum) + return new; } - - return self.setCapacity(gpa, better_capacity); } /// Modify the array so that it can hold at least `additional_count` **more** items. @@ -560,7 +577,7 @@ pub fn MultiArrayList(comptime T: type) type { self.sortInternal(a, b, ctx, .unstable); } - fn capacityInBytes(capacity: usize) usize { + pub fn capacityInBytes(capacity: usize) usize { comptime var elem_bytes: usize = 0; inline for (sizes.bytes) |size| elem_bytes += size; return elem_bytes * capacity; @@ -570,10 +587,12 @@ pub fn MultiArrayList(comptime T: type) type { return self.bytes[0..capacityInBytes(self.capacity)]; } + /// Returns the amount of memory used by this list, in bytes. pub fn memoryCost(self: Self) usize { return capacityInBytes(self.capacity); } + /// Zero-initialize all allocated memory. pub fn zero(self: Self) void { @memset(self.allocatedBytes(), 0); } @@ -617,7 +636,6 @@ pub fn MultiArrayList(comptime T: type) type { } const builtin = @import("builtin"); -const CheckedAllocPtr = @import("./safety.zig").AllocPtr; const bun = @import("bun"); const assert = bun.assert; diff --git a/src/comptime_string_map.zig b/src/comptime_string_map.zig index 1c07b5bf59..4d65cf870f 100644 --- a/src/comptime_string_map.zig +++ b/src/comptime_string_map.zig @@ -190,28 +190,16 @@ pub fn ComptimeStringMapWithKeyType(comptime KeyType: type, comptime V: type, co return null; } - /// Caller must ensure that the input is a string. + /// Throws if toString() throws. pub fn fromJS(globalThis: *jsc.JSGlobalObject, input: jsc.JSValue) bun.JSError!?V { - if (comptime bun.Environment.allow_assert) { - if (!input.isString()) { - @panic("ComptimeStringMap.fromJS: input is not a string"); - } - } - const str = try bun.String.fromJS(input, globalThis); bun.assert(str.tag != .Dead); defer str.deref(); return getWithEql(str, bun.String.eqlComptime); } - /// Caller must ensure that the input is a string. + /// Throws if toString() throws. pub fn fromJSCaseInsensitive(globalThis: *jsc.JSGlobalObject, input: jsc.JSValue) bun.JSError!?V { - if (comptime bun.Environment.allow_assert) { - if (!input.isString()) { - @panic("ComptimeStringMap.fromJS: input is not a string"); - } - } - const str = try bun.String.fromJS(input, globalThis); bun.assert(str.tag != .Dead); defer str.deref(); diff --git a/src/crash_handler.zig b/src/crash_handler.zig index 3755b676a2..a82f3a8c10 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -903,6 +903,12 @@ extern "c" fn gnu_get_libc_version() ?[*:0]const u8; export var Bun__reported_memory_size: usize = 0; pub fn printMetadata(writer: anytype) !void { + if (comptime bun.Environment.isDebug) { + if (Output.isAIAgent()) { + return; + } + } + if (Output.enable_ansi_colors) { try writer.writeAll(Output.prettyFmt("", true)); } @@ -1629,10 +1635,12 @@ pub fn dumpStackTrace(trace: std.builtin.StackTrace, limits: WriteStackTraceLimi return; }, .linux => { - // Linux doesnt seem to be able to decode it's own debug info. - // TODO(@paperclover): see if zig 0.14 fixes this - WTF__DumpStackTrace(trace.instruction_addresses.ptr, trace.instruction_addresses.len); - return; + if (!bun.Environment.isDebug) { + // Linux doesnt seem to be able to decode it's own debug info. + // TODO(@paperclover): see if zig 0.14 fixes this + WTF__DumpStackTrace(trace.instruction_addresses.ptr, trace.instruction_addresses.len); + return; + } }, else => { // Assume debug symbol tooling is reliable. @@ -1682,25 +1690,31 @@ pub fn dumpStackTrace(trace: std.builtin.StackTrace, limits: WriteStackTraceLimi argv.append(std.fmt.allocPrint(alloc, "0x{X}", .{line.address}) catch return) catch return; } - // std.process is used here because bun.spawnSync with libuv does not work within - // the crash handler. - const proc = std.process.Child.run(.{ - .allocator = alloc, - .argv = argv.items, - }) catch { + var child = std.process.Child.init(argv.items, alloc); + child.stdin_behavior = .Inherit; + child.stdout_behavior = .Inherit; + child.stderr_behavior = .Inherit; + + child.expand_arg0 = .expand; + child.progress_node = std.Progress.Node.none; + + child.spawn() catch { stderr.print("Failed to invoke command: {s}\n", .{bun.fmt.fmtSlice(argv.items, " ")}) catch return; if (bun.Environment.isWindows) { stderr.print("(You can compile pdb-addr2line from https://github.com/oven-sh/bun.report, cd pdb-addr2line && cargo build)\n", .{}) catch return; } return; }; - if (proc.term != .Exited or proc.term.Exited != 0) { + + const result = child.spawnAndWait() catch { stderr.print("Failed to invoke command: {s}\n", .{bun.fmt.fmtSlice(argv.items, " ")}) catch return; + return; + }; + + if (result != .Exited or result.Exited != 0) { + stderr.print("Failed to invoke command: {s}\n", .{bun.fmt.fmtSlice(argv.items, " ")}) catch return; + return; } - defer alloc.free(proc.stderr); - defer alloc.free(proc.stdout); - stderr.writeAll(proc.stdout) catch return; - stderr.writeAll(proc.stderr) catch return; } pub fn dumpCurrentStackTrace(first_address: ?usize, limits: WriteStackTraceLimits) void { diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 8da33f6467..9050e98730 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -69,6 +69,7 @@ pub const create_bun_socket_error_t = enum(c_int) { load_ca_file, invalid_ca_file, invalid_ca, + invalid_ciphers, pub fn toJS(this: create_bun_socket_error_t, globalObject: *jsc.JSGlobalObject) jsc.JSValue { return switch (this) { @@ -79,6 +80,7 @@ pub const create_bun_socket_error_t = enum(c_int) { .load_ca_file => globalObject.ERR(.BORINGSSL, "Failed to load CA file", .{}).toJS(), .invalid_ca_file => globalObject.ERR(.BORINGSSL, "Invalid CA file", .{}).toJS(), .invalid_ca => globalObject.ERR(.BORINGSSL, "Invalid CA", .{}).toJS(), + .invalid_ciphers => globalObject.ERR(.BORINGSSL, "Invalid ciphers", .{}).toJS(), }; } }; @@ -144,6 +146,14 @@ pub const LIBUS_SOCKET_DESCRIPTOR = switch (bun.Environment.isWindows) { false => i32, }; +const c = struct { + pub extern fn us_get_default_ciphers() [*:0]const u8; +}; + +pub fn get_default_ciphers() [:0]const u8 { + return c.us_get_default_ciphers()[0..bun.len(c.us_get_default_ciphers()) :0]; +} + const bun = @import("bun"); const Environment = bun.Environment; const jsc = bun.jsc; diff --git a/src/deps/uws/InternalLoopData.zig b/src/deps/uws/InternalLoopData.zig index 69918ec02a..e750ce08be 100644 --- a/src/deps/uws/InternalLoopData.zig +++ b/src/deps/uws/InternalLoopData.zig @@ -2,6 +2,7 @@ pub const InternalLoopData = extern struct { pub const us_internal_async = opaque {}; sweep_timer: ?*Timer, + sweep_timer_count: i32, wakeup_async: ?*us_internal_async, last_write_failed: i32, head: ?*SocketContext, diff --git a/src/http.zig b/src/http.zig index 15d0785a8e..d5389563b1 100644 --- a/src/http.zig +++ b/src/http.zig @@ -2424,6 +2424,7 @@ pub const ThreadlocalAsyncHTTP = struct { async_http: AsyncHTTP, }; +pub const ETag = @import("./http/ETag.zig"); pub const Method = @import("./http/Method.zig").Method; pub const Headers = @import("./http/Headers.zig"); pub const MimeType = @import("./http/MimeType.zig"); diff --git a/src/http/ETag.zig b/src/http/ETag.zig new file mode 100644 index 0000000000..416a4e8aff --- /dev/null +++ b/src/http/ETag.zig @@ -0,0 +1,65 @@ +const ETag = @This(); + +/// Parse a single entity tag from a string, returns the tag without quotes and whether it's weak +fn parse(tag_str: []const u8) struct { tag: []const u8, is_weak: bool } { + var str = std.mem.trim(u8, tag_str, " \t"); + + // Check for weak indicator + var is_weak = false; + if (bun.strings.hasPrefix(str, "W/")) { + is_weak = true; + str = str[2..]; + str = std.mem.trimLeft(u8, str, " \t"); + } + + // Remove surrounding quotes + if (str.len >= 2 and str[0] == '"' and str[str.len - 1] == '"') { + str = str[1 .. str.len - 1]; + } + + return .{ .tag = str, .is_weak = is_weak }; +} + +/// Perform weak comparison between two entity tags according to RFC 9110 Section 8.8.3.2 +fn weakMatch(tag1: []const u8, is_weak1: bool, tag2: []const u8, is_weak2: bool) bool { + _ = is_weak1; + _ = is_weak2; + // For weak comparison, we only compare the opaque tag values, ignoring weak indicators + return std.mem.eql(u8, tag1, tag2); +} + +pub fn appendToHeaders(bytes: []const u8, headers: *bun.http.Headers) !void { + const hash = std.hash.XxHash64.hash(0, bytes); + + var etag_buf: [40]u8 = undefined; + const etag_str = std.fmt.bufPrint(&etag_buf, "\"{}\"", .{bun.fmt.hexIntLower(hash)}) catch unreachable; + try headers.append("etag", etag_str); +} + +pub fn ifNoneMatch( + /// "ETag" header + etag: []const u8, + /// "If-None-Match" header + if_none_match: []const u8, +) bool { + const our_parsed = parse(etag); + + // Handle "*" case + if (std.mem.eql(u8, std.mem.trim(u8, if_none_match, " \t"), "*")) { + return true; // Condition is false, so we should return 304 + } + + // Parse comma-separated list of entity tags + var iter = std.mem.splitScalar(u8, if_none_match, ','); + while (iter.next()) |tag_str| { + const parsed = parse(tag_str); + if (weakMatch(our_parsed.tag, our_parsed.is_weak, parsed.tag, parsed.is_weak)) { + return true; // Condition is false, so we should return 304 + } + } + + return false; // Condition is true, continue with normal processing +} + +const bun = @import("bun"); +const std = @import("std"); diff --git a/src/http/HTTPThread.zig b/src/http/HTTPThread.zig index 354cf93483..deb4187602 100644 --- a/src/http/HTTPThread.zig +++ b/src/http/HTTPThread.zig @@ -196,7 +196,7 @@ pub fn init(opts: *const InitOpts) void { pub fn onStart(opts: InitOpts) void { Output.Source.configureNamedThread("HTTP Client"); bun.http.default_arena = Arena.init() catch unreachable; - bun.http.default_allocator = bun.http.default_arena.allocator(); + bun.http.default_allocator = bun.default_allocator; const loop = bun.jsc.MiniEventLoop.initGlobal(null); diff --git a/src/http/websocket_client.zig b/src/http/websocket_client.zig index 4d681d9ee7..e6ef2d8f37 100644 --- a/src/http/websocket_client.zig +++ b/src/http/websocket_client.zig @@ -984,6 +984,48 @@ pub fn NewWebSocketClient(comptime ssl: bool) type { return !this.tcp.isClosed() and !this.tcp.isShutdown(); } + pub fn writeBlob( + this: *WebSocket, + blob_value: jsc.JSValue, + op: u8, + ) callconv(.C) void { + if (!this.hasTCP() or op > 0xF) { + this.dispatchAbruptClose(ErrorCode.ended); + return; + } + + const opcode: Opcode = @enumFromInt(op); + + // Cast the JSValue to a Blob + if (blob_value.as(jsc.WebCore.Blob)) |blob| { + // Get the shared view of the blob data + const data = blob.sharedView(); + if (data.len == 0) { + // Empty blob, send empty frame + const bytes = Copy{ .bytes = &[0]u8{} }; + _ = this.sendData(bytes, !this.hasBackpressure(), opcode); + return; + } + + // Send the blob data similar to writeBinaryData + const bytes = Copy{ .bytes = data }; + + // Fast path for small blobs + const frame_size = WebsocketHeader.frameSizeIncludingMask(data.len); + if (!this.hasBackpressure() and frame_size < stack_frame_size) { + var inline_buf: [stack_frame_size]u8 = undefined; + bytes.copy(this.globalThis, inline_buf[0..frame_size], data.len, opcode); + _ = this.enqueueEncodedBytes(this.tcp, inline_buf[0..frame_size]); + return; + } + + _ = this.sendData(bytes, !this.hasBackpressure(), opcode); + } else { + // Invalid blob, close connection + this.dispatchAbruptClose(ErrorCode.ended); + } + } + pub fn writeString( this: *WebSocket, str_: *const jsc.ZigString, @@ -1216,6 +1258,7 @@ pub fn NewWebSocketClient(comptime ssl: bool) type { @export(&memoryCost, .{ .name = "Bun__" ++ name ++ "__memoryCost" }); @export(®ister, .{ .name = "Bun__" ++ name ++ "__register" }); @export(&writeBinaryData, .{ .name = "Bun__" ++ name ++ "__writeBinaryData" }); + @export(&writeBlob, .{ .name = "Bun__" ++ name ++ "__writeBlob" }); @export(&writeString, .{ .name = "Bun__" ++ name ++ "__writeString" }); } } diff --git a/src/install/PackageManager.zig b/src/install/PackageManager.zig index fcb33f68ed..eab0caf21f 100644 --- a/src/install/PackageManager.zig +++ b/src/install/PackageManager.zig @@ -178,6 +178,7 @@ pub const Subcommand = enum { return switch (this) { .outdated => true, .install => true, + .update => true, // .pack => true, // .add => true, else => false, diff --git a/src/install/PackageManager/CommandLineArguments.zig b/src/install/PackageManager/CommandLineArguments.zig index 84ed4f8d10..6ca71a5ca0 100644 --- a/src/install/PackageManager/CommandLineArguments.zig +++ b/src/install/PackageManager/CommandLineArguments.zig @@ -67,7 +67,9 @@ pub const install_params: []const ParamType = &(shared_params ++ [_]ParamType{ pub const update_params: []const ParamType = &(shared_params ++ [_]ParamType{ clap.parseParam("--latest Update packages to their latest versions") catch unreachable, clap.parseParam("-i, --interactive Show an interactive list of outdated packages to select for update") catch unreachable, - clap.parseParam(" ... \"name\" of packages to update") catch unreachable, + clap.parseParam("--filter ... Update packages for the matching workspaces") catch unreachable, + clap.parseParam("-r, --recursive Update packages in all workspaces") catch unreachable, + clap.parseParam(" ... \"name\" of packages to update") catch unreachable, }); pub const pm_params: []const ParamType = &(shared_params ++ [_]ParamType{ @@ -123,7 +125,8 @@ const patch_commit_params: []const ParamType = &(shared_params ++ [_]ParamType{ const outdated_params: []const ParamType = &(shared_params ++ [_]ParamType{ // clap.parseParam("--json Output outdated information in JSON format") catch unreachable, - clap.parseParam("-F, --filter ... Display outdated dependencies for each matching workspace") catch unreachable, + clap.parseParam("-F, --filter ... Display outdated dependencies for each matching workspace") catch unreachable, + clap.parseParam("-r, --recursive Check outdated packages in all workspaces") catch unreachable, clap.parseParam(" ... Package patterns to filter by") catch unreachable, }); @@ -189,6 +192,7 @@ no_summary: bool = false, latest: bool = false, interactive: bool = false, json_output: bool = false, +recursive: bool = false, filters: []const string = &.{}, pack_destination: string = "", @@ -785,6 +789,7 @@ pub fn parse(allocator: std.mem.Allocator, comptime subcommand: Subcommand) !Com if (comptime subcommand == .outdated) { // fake --dry-run, we don't actually resolve+clean the lockfile cli.dry_run = true; + cli.recursive = args.flag("--recursive"); // cli.json_output = args.flag("--json"); } @@ -898,6 +903,7 @@ pub fn parse(allocator: std.mem.Allocator, comptime subcommand: Subcommand) !Com if (comptime subcommand == .update) { cli.latest = args.flag("--latest"); cli.interactive = args.flag("--interactive"); + cli.recursive = args.flag("--recursive"); } const specified_backend: ?PackageInstall.Method = brk: { diff --git a/src/install/PackageManager/PackageJSONEditor.zig b/src/install/PackageManager/PackageJSONEditor.zig index 67eae120ce..43f0225a34 100644 --- a/src/install/PackageManager/PackageJSONEditor.zig +++ b/src/install/PackageManager/PackageJSONEditor.zig @@ -5,6 +5,17 @@ const dependency_groups = &.{ .{ "peerDependencies", .{ .peer = true } }, }; +fn resolveCatalogDependency(manager: *PackageManager, dep: Dependency) ?Dependency.Version { + return if (dep.version.tag == .catalog) blk: { + const catalog_dep = manager.lockfile.catalogs.get( + manager.lockfile, + dep.version.value.catalog, + dep.name, + ) orelse return null; + break :blk catalog_dep.version; + } else dep.version; +} + pub const EditOptions = struct { exact_versions: bool = false, add_trusted_dependencies: bool = false, @@ -217,8 +228,8 @@ pub fn editUpdateNoArgs( const version_literal = try value.asStringCloned(allocator) orelse bun.outOfMemory(); var tag = Dependency.Version.Tag.infer(version_literal); - // only updating dependencies with npm versions, and dist-tags if `--latest`. - if (tag != .npm and (tag != .dist_tag or !manager.options.do.update_to_latest)) continue; + // only updating dependencies with npm versions, dist-tags if `--latest`, and catalog versions. + if (tag != .npm and (tag != .dist_tag or !manager.options.do.update_to_latest) and tag != .catalog) continue; var alias_at_index: ?usize = null; if (strings.hasPrefixComptime(strings.trim(version_literal, &strings.whitespace_chars), "npm:")) { @@ -226,7 +237,7 @@ pub fn editUpdateNoArgs( // e.g. "dep": "npm:@foo/bar@1.2.3" if (strings.lastIndexOfChar(version_literal, '@')) |at_index| { tag = Dependency.Version.Tag.infer(version_literal[at_index + 1 ..]); - if (tag != .npm and (tag != .dist_tag or !manager.options.do.update_to_latest)) continue; + if (tag != .npm and (tag != .dist_tag or !manager.options.do.update_to_latest) and tag != .catalog) continue; alias_at_index = at_index; } } @@ -291,7 +302,8 @@ pub fn editUpdateNoArgs( const workspace_dep_name = workspace_dep.name.slice(string_buf); if (!strings.eqlLong(workspace_dep_name, dep_name, true)) continue; - if (workspace_dep.version.npm()) |npm_version| { + const resolved_version = resolveCatalogDependency(manager, workspace_dep) orelse workspace_dep.version; + if (resolved_version.npm()) |npm_version| { // It's possible we inserted a dependency that won't update (version is an exact version). // If we find one, skip to keep the original version literal. if (!manager.options.do.update_to_latest and npm_version.version.isExact()) break :updated; diff --git a/src/install/PackageManager/PackageManagerLifecycle.zig b/src/install/PackageManager/PackageManagerLifecycle.zig index 4b7a443a8a..59e76aeed5 100644 --- a/src/install/PackageManager/PackageManagerLifecycle.zig +++ b/src/install/PackageManager/PackageManagerLifecycle.zig @@ -248,7 +248,8 @@ pub fn loadRootLifecycleScripts(this: *PackageManager, root_package: Package) vo } } -/// Called from multiple threads +/// Used to be called from multiple threads; now single-threaded +/// TODO: re-evaluate whether some variables still need to be atomic pub fn spawnPackageLifecycleScripts( this: *PackageManager, ctx: Command.Context, diff --git a/src/install/PackageManager/PackageManagerOptions.zig b/src/install/PackageManager/PackageManagerOptions.zig index 26c023c1b2..98cf61610d 100644 --- a/src/install/PackageManager/PackageManagerOptions.zig +++ b/src/install/PackageManager/PackageManagerOptions.zig @@ -568,6 +568,7 @@ pub fn load( } this.do.update_to_latest = cli.latest; + this.do.recursive = cli.recursive; if (cli.positionals.len > 0) { this.positionals = cli.positionals; @@ -666,7 +667,8 @@ pub const Do = packed struct(u16) { trust_dependencies_from_args: bool = false, update_to_latest: bool = false, analyze: bool = false, - _: u4 = 0, + recursive: bool = false, + _: u3 = 0, }; pub const Enable = packed struct(u16) { diff --git a/src/install/PackageManager/runTasks.zig b/src/install/PackageManager/runTasks.zig index 344073430a..9d7c09fa5b 100644 --- a/src/install/PackageManager/runTasks.zig +++ b/src/install/PackageManager/runTasks.zig @@ -87,6 +87,28 @@ pub fn runTasks( .blocked => { installer.onTaskBlocked(task.entry_id); }, + .run_scripts => |list| { + const entries = installer.store.entries.slice(); + + const node_id = entries.items(.node_id)[task.entry_id.get()]; + const dep_id = installer.store.nodes.items(.dep_id)[node_id.get()]; + const dep = installer.lockfile.buffers.dependencies.items[dep_id]; + installer.manager.spawnPackageLifecycleScripts( + installer.command_ctx, + list.*, + dep.behavior.optional, + false, + .{ + .entry_id = task.entry_id, + .installer = installer, + }, + ) catch |err| { + // .monotonic is okay for the same reason as `.done`: we popped this + // task from the `UnboundedQueue`, and the task is no longer running. + entries.items(.step)[task.entry_id.get()].store(.done, .monotonic); + installer.onTaskFail(task.entry_id, .{ .run_scripts = err }); + }; + }, .done => { if (comptime Environment.ci_assert) { // .monotonic is okay because we should have already synchronized with the diff --git a/src/install/PackageManager/updatePackageJSONAndInstall.zig b/src/install/PackageManager/updatePackageJSONAndInstall.zig index c603555ec0..e4288b9f11 100644 --- a/src/install/PackageManager/updatePackageJSONAndInstall.zig +++ b/src/install/PackageManager/updatePackageJSONAndInstall.zig @@ -22,6 +22,7 @@ pub fn updatePackageJSONAndInstallWithManager( Global.exit(0); }, + .update => {}, else => {}, } } diff --git a/src/install/isolated_install/Installer.zig b/src/install/isolated_install/Installer.zig index d8ff53a1c5..258adec2fd 100644 --- a/src/install/isolated_install/Installer.zig +++ b/src/install/isolated_install/Installer.zig @@ -27,7 +27,16 @@ pub const Installer = struct { /// Called from main thread pub fn startTask(this: *Installer, entry_id: Store.Entry.Id) void { const task = &this.tasks[entry_id.get()]; - bun.debugAssert(task.result == .none or task.result == .blocked); + bun.debugAssert(switch (task.result) { + // first time starting the task + .none => true, + // the task returned to the main thread because it was blocked + .blocked => true, + // the task returned to the main thread to spawn some scripts + .run_scripts => true, + else => false, + }); + task.result = .none; this.manager.thread_pool.schedule(.from(&task.task)); } @@ -272,31 +281,22 @@ pub const Installer = struct { none, err: Error, blocked, + run_scripts: *Package.Scripts.List, done, }; - const Error = union(Step) { + const Error = union(enum) { link_package: sys.Error, symlink_dependencies: sys.Error, - check_if_blocked, - symlink_dependency_binaries, - run_preinstall: anyerror, + run_scripts: anyerror, binaries: anyerror, - @"run (post)install and (pre/post)prepare": anyerror, - done, - blocked, pub fn clone(this: *const Error, allocator: std.mem.Allocator) Error { return switch (this.*) { .link_package => |err| .{ .link_package = err.clone(allocator) }, .symlink_dependencies => |err| .{ .symlink_dependencies = err.clone(allocator) }, - .check_if_blocked => .check_if_blocked, - .symlink_dependency_binaries => .symlink_dependency_binaries, - .run_preinstall => |err| .{ .run_preinstall = err }, .binaries => |err| .{ .binaries = err }, - .@"run (post)install and (pre/post)prepare" => |err| .{ .@"run (post)install and (pre/post)prepare" = err }, - .done => .done, - .blocked => .blocked, + .run_scripts => |err| .{ .run_scripts = err }, }; } }; @@ -349,12 +349,15 @@ pub const Installer = struct { const Yield = union(enum) { yield, + run_scripts: *Package.Scripts.List, done, blocked, fail: Error, pub fn failure(e: Error) Yield { - return .{ .fail = e }; + // clone here in case a path is kept in a buffer that + // will be freed at the end of the current scope. + return .{ .fail = e.clone(bun.default_allocator) }; } }; @@ -870,11 +873,12 @@ pub const Installer = struct { dep.name.slice(string_buf), &pkg_res, ) catch |err| { - return .failure(.{ .run_preinstall = err }); + return .failure(.{ .run_scripts = err }); }; if (scripts_list) |list| { - entry_scripts[this.entry_id.get()] = bun.create(bun.default_allocator, Package.Scripts.List, list); + const clone = bun.create(bun.default_allocator, Package.Scripts.List, list); + entry_scripts[this.entry_id.get()] = clone; if (is_trusted_through_update_request) { const trusted_dep_to_add = try installer.manager.allocator.dupe(u8, dep.name.slice(string_buf)); @@ -897,20 +901,7 @@ pub const Installer = struct { continue :next_step this.nextStep(current_step); } - installer.manager.spawnPackageLifecycleScripts( - installer.command_ctx, - list, - dep.behavior.optional, - false, - .{ - .entry_id = this.entry_id, - .installer = installer, - }, - ) catch |err| { - return .failure(.{ .run_preinstall = err }); - }; - - return .yield; + return .{ .run_scripts = clone }; } } @@ -989,26 +980,11 @@ pub const Installer = struct { continue :next_step this.nextStep(current_step); } - const dep = installer.lockfile.buffers.dependencies.items[dep_id]; - - installer.manager.spawnPackageLifecycleScripts( - installer.command_ctx, - list.*, - dep.behavior.optional, - false, - .{ - .entry_id = this.entry_id, - .installer = installer, - }, - ) catch |err| { - return .failure(.{ .@"run (post)install and (pre/post)prepare" = err }); - }; - // when these scripts finish the package install will be // complete. the task does not have anymore work to complete // so it does not return to the thread pool. - return .yield; + return .{ .run_scripts = list }; }, .done => { @@ -1032,6 +1008,14 @@ pub const Installer = struct { switch (res) { .yield => {}, + .run_scripts => |list| { + if (comptime Environment.ci_assert) { + bun.assertWithLocation(this.installer.store.entries.items(.scripts)[this.entry_id.get()] != null, @src()); + } + this.result = .{ .run_scripts = list }; + this.installer.task_queue.push(this); + this.installer.manager.wake(); + }, .done => { if (comptime Environment.ci_assert) { // .monotonic is okay because this should have been set by this thread. @@ -1056,7 +1040,7 @@ pub const Installer = struct { bun.assertWithLocation(this.installer.store.entries.items(.step)[this.entry_id.get()].load(.monotonic) != .done, @src()); } this.installer.store.entries.items(.step)[this.entry_id.get()].store(.done, .release); - this.result = .{ .err = err.clone(bun.default_allocator) }; + this.result = .{ .err = err }; this.installer.task_queue.push(this); this.installer.manager.wake(); }, diff --git a/src/install/lifecycle_script_runner.zig b/src/install/lifecycle_script_runner.zig index 55bf5bbe3c..3fb5bb43b7 100644 --- a/src/install/lifecycle_script_runner.zig +++ b/src/install/lifecycle_script_runner.zig @@ -112,7 +112,8 @@ pub const LifecycleScriptSubprocess = struct { } } - /// Called from multiple threads in the case of isolated installs + /// Used to be called from multiple threads during isolated installs; now single-threaded + /// TODO: re-evaluate whether some variables still need to be atomic pub fn spawnNextScript(this: *LifecycleScriptSubprocess, next_script_index: u8) !void { bun.analytics.Features.lifecycle_scripts += 1; diff --git a/src/install/lockfile/Package/Scripts.zig b/src/install/lockfile/Package/Scripts.zig index 2dfe3bf5c4..b330324fb7 100644 --- a/src/install/lockfile/Package/Scripts.zig +++ b/src/install/lockfile/Package/Scripts.zig @@ -23,16 +23,6 @@ pub const Scripts = extern struct { cwd: stringZ, package_name: string, - pub fn initPreinstall(allocator: std.mem.Allocator, preinstall: string, cwd: string, package_name: string) @This() { - return .{ - .items = .{ allocator.dupe(u8, preinstall) catch bun.outOfMemory(), null, null, null, null, null }, - .first_index = 0, - .total = 1, - .cwd = allocator.dupeZ(u8, cwd) catch bun.outOfMemory(), - .package_name = allocator.dupe(u8, package_name) catch bun.outOfMemory(), - }; - } - pub fn printScripts( this: Package.Scripts.List, resolution: *const Resolution, diff --git a/src/install/migration.zig b/src/install/migration.zig index 31a813de1b..c7b68937eb 100644 --- a/src/install/migration.zig +++ b/src/install/migration.zig @@ -52,6 +52,38 @@ pub fn detectAndLoadOtherLockfile( return migrate_result; } + yarn: { + var timer = std.time.Timer.start() catch unreachable; + const lockfile = File.openat(dir, "yarn.lock", bun.O.RDONLY, 0).unwrap() catch break :yarn; + defer lockfile.close(); + const data = lockfile.readToEnd(allocator).unwrap() catch break :yarn; + const migrate_result = @import("./yarn.zig").migrateYarnLockfile(this, manager, allocator, log, data, dir) catch |err| { + if (Environment.isDebug) { + bun.handleErrorReturnTrace(err, @errorReturnTrace()); + + Output.prettyErrorln("Error: {s}", .{@errorName(err)}); + log.print(Output.errorWriter()) catch {}; + Output.prettyErrorln("Invalid yarn.lock\nIn a release build, this would ignore and do a fresh install.\nAborting", .{}); + Global.exit(1); + } + return LoadResult{ .err = .{ + .step = .migrating, + .value = err, + .lockfile_path = "yarn.lock", + .format = .binary, + } }; + }; + + if (migrate_result == .ok) { + Output.printElapsed(@as(f64, @floatFromInt(timer.read())) / std.time.ns_per_ms); + Output.prettyError(" ", .{}); + Output.prettyErrorln("migrated lockfile from yarn.lock", .{}); + Output.flush(); + } + + return migrate_result; + } + return LoadResult{ .not_found = {} }; } diff --git a/src/install/yarn.zig b/src/install/yarn.zig new file mode 100644 index 0000000000..febc70c413 --- /dev/null +++ b/src/install/yarn.zig @@ -0,0 +1,1718 @@ +pub const YarnLock = struct { + const Entry = struct { + specs: []const []const u8, + version: string, + resolved: ?string = null, + integrity: ?string = null, + dependencies: ?bun.StringHashMap(string) = null, + optionalDependencies: ?bun.StringHashMap(string) = null, + peerDependencies: ?bun.StringHashMap(string) = null, + devDependencies: ?bun.StringHashMap(string) = null, + commit: ?string = null, + workspace: bool = false, + file: ?string = null, + os: ?[]const []const u8 = null, + cpu: ?[]const []const u8 = null, + git_repo_name: ?string = null, + + pub fn deinit(self: *Entry, allocator: Allocator) void { + allocator.free(self.specs); + if (self.dependencies) |*deps| { + deps.deinit(); + } + if (self.optionalDependencies) |*deps| { + deps.deinit(); + } + if (self.peerDependencies) |*deps| { + deps.deinit(); + } + if (self.devDependencies) |*deps| { + deps.deinit(); + } + if (self.os) |os_list| { + allocator.free(os_list); + } + if (self.cpu) |cpu_list| { + allocator.free(cpu_list); + } + if (self.git_repo_name) |name| { + allocator.free(name); + } + } + + pub fn getNameFromSpec(spec: []const u8) []const u8 { + const unquoted = if (spec[0] == '"' and spec[spec.len - 1] == '"') + spec[1 .. spec.len - 1] + else + spec; + + if (unquoted[0] == '@') { + if (strings.indexOf(unquoted[1..], "@")) |second_at| { + const end_idx = second_at + 1; + return unquoted[0..end_idx]; + } + return unquoted; + } + + if (strings.indexOf(unquoted, "@npm:")) |npm_idx| { + return unquoted[0..npm_idx]; + } else if (strings.indexOf(unquoted, "@https://")) |url_idx| { + return unquoted[0..url_idx]; + } else if (strings.indexOf(unquoted, "@git+")) |git_idx| { + return unquoted[0..git_idx]; + } else if (strings.indexOf(unquoted, "@github:")) |gh_idx| { + return unquoted[0..gh_idx]; + } else if (strings.indexOf(unquoted, "@file:")) |file_idx| { + return unquoted[0..file_idx]; + } else if (strings.indexOf(unquoted, "@")) |idx| { + return unquoted[0..idx]; + } + return unquoted; + } + + pub fn getVersionFromSpec(spec: []const u8) ?[]const u8 { + const unquoted = if (spec[0] == '"' and spec[spec.len - 1] == '"') + spec[1 .. spec.len - 1] + else + spec; + + if (unquoted[0] == '@') { + if (strings.indexOfChar(unquoted[1..], '@')) |second_at_pos| { + const version_start = second_at_pos + "@".len + 1; + const version_part = unquoted[version_start..]; + + if (strings.hasPrefixComptime(version_part, "npm:") and version_part.len > 4) { + return version_part["npm:".len..]; + } + return version_part; + } + return null; + } else if (strings.indexOf(unquoted, "@npm:")) |npm_idx| { + const after_npm = npm_idx + "npm:".len + 1; + if (after_npm < unquoted.len) { + return unquoted[after_npm..]; + } + return null; + } else if (strings.indexOf(unquoted, "@https://")) |url_idx| { + const after_at = url_idx + '@'.len; + if (after_at < unquoted.len) { + return unquoted[after_at..]; + } + return null; + } else if (strings.indexOf(unquoted, "@git+")) |git_idx| { + const after_at = git_idx + '@'.len; + if (after_at < unquoted.len) { + return unquoted[after_at..]; + } + return null; + } else if (strings.indexOf(unquoted, "@github:")) |gh_idx| { + const after_at = gh_idx + '@'.len; + if (after_at < unquoted.len) { + return unquoted[after_at..]; + } + return null; + } else if (strings.indexOf(unquoted, "@file:")) |file_idx| { + const after_at = file_idx + '@'.len; + if (after_at < unquoted.len) { + return unquoted[after_at..]; + } + return null; + } else if (strings.indexOf(unquoted, "@")) |idx| { + const after_at = idx + '@'.len; + if (after_at < unquoted.len) { + return unquoted[after_at..]; + } + return null; + } + return null; + } + + pub fn isGitDependency(version: []const u8) bool { + return strings.hasPrefixComptime(version, "git+") or + strings.hasPrefixComptime(version, "git://") or + strings.hasPrefixComptime(version, "github:") or + strings.hasPrefixComptime(version, "https://github.com/"); + } + + pub fn isNpmAlias(version: []const u8) bool { + return strings.hasPrefixComptime(version, "npm:"); + } + + pub fn isRemoteTarball(version: []const u8) bool { + return strings.hasPrefixComptime(version, "https://") and strings.endsWithComptime(version, ".tgz"); + } + + pub fn isWorkspaceDependency(version: []const u8) bool { + return strings.hasPrefixComptime(version, "workspace:") or + strings.eqlComptime(version, "*"); + } + + pub fn isFileDependency(version: []const u8) bool { + return strings.hasPrefixComptime(version, "file:") or + strings.hasPrefixComptime(version, "./") or + strings.hasPrefixComptime(version, "../"); + } + + pub fn parseGitUrl(self: *const YarnLock, version: []const u8) !struct { url: []const u8, commit: ?[]const u8, owner: ?[]const u8, repo: ?[]const u8 } { + var url = version; + var commit: ?[]const u8 = null; + var owner: ?[]const u8 = null; + var repo: ?[]const u8 = null; + + if (strings.hasPrefixComptime(url, "git+")) { + url = url[4..]; + } + + if (strings.indexOf(url, "#")) |hash_idx| { + commit = url[hash_idx + 1 ..]; + url = url[0..hash_idx]; + } + + if (strings.hasPrefixComptime(version, "github:")) { + const github_path = version["github:".len..]; + const path_without_commit = if (strings.indexOf(github_path, "#")) |idx| github_path[0..idx] else github_path; + + if (strings.indexOf(path_without_commit, "/")) |slash_idx| { + owner = path_without_commit[0..slash_idx]; + repo = path_without_commit[slash_idx + 1 ..]; + } + url = try std.fmt.allocPrint( + self.allocator, + "https://github.com/{s}", + .{path_without_commit}, + ); + } else if (strings.contains(url, "github.com")) { + var remaining = url; + if (strings.indexOf(remaining, "github.com/")) |idx| { + remaining = remaining[idx + "github.com/".len ..]; + } + if (strings.indexOf(remaining, "/")) |slash_idx| { + owner = remaining[0..slash_idx]; + const after_owner = remaining[slash_idx + 1 ..]; + if (strings.endsWithComptime(after_owner, ".git")) { + repo = after_owner[0 .. after_owner.len - ".git".len]; + } else { + repo = after_owner; + } + } + } + + return .{ .url = url, .commit = commit, .owner = owner, .repo = repo }; + } + + pub fn parseNpmAlias(version: []const u8) struct { package: []const u8, version: []const u8 } { + if (version.len <= 4) { + return .{ .package = "", .version = "*" }; + } + + const npm_part = version[4..]; + if (strings.indexOf(npm_part, "@")) |at_idx| { + return .{ + .package = npm_part[0..at_idx], + .version = if (at_idx + 1 < npm_part.len) npm_part[at_idx + 1 ..] else "*", + }; + } + return .{ .package = npm_part, .version = "*" }; + } + + pub fn getPackageNameFromResolvedUrl(url: []const u8) ?[]const u8 { + if (strings.indexOf(url, "/-/")) |dash_idx| { + var slash_count: usize = 0; + var last_slash: usize = 0; + var second_last_slash: usize = 0; + + var i = dash_idx; + while (i > 0) : (i -= 1) { + if (url[i - 1] == '/') { + slash_count += 1; + if (slash_count == 1) { + last_slash = i - 1; + } else if (slash_count == 2) { + second_last_slash = i - 1; + break; + } + } + } + + if (last_slash < dash_idx and url[last_slash + 1] == '@') { + return url[second_last_slash + 1 .. dash_idx]; + } else { + return url[last_slash + 1 .. dash_idx]; + } + } + + return null; + } + }; + + entries: std.ArrayList(Entry), + allocator: Allocator, + + pub fn init(allocator: Allocator) YarnLock { + return .{ + .entries = std.ArrayList(Entry).init(allocator), + .allocator = allocator, + }; + } + + pub fn deinit(self: *YarnLock) void { + for (self.entries.items) |*entry| { + entry.deinit(self.allocator); + } + self.entries.deinit(); + } + + pub fn parse(self: *YarnLock, content: []const u8) !void { + var lines = strings.split(content, "\n"); + var current_entry: ?Entry = null; + var current_specs = std.ArrayList([]const u8).init(self.allocator); + defer current_specs.deinit(); + + var current_deps: ?bun.StringHashMap(string) = null; + var current_optional_deps: ?bun.StringHashMap(string) = null; + var current_peer_deps: ?bun.StringHashMap(string) = null; + var current_dev_deps: ?bun.StringHashMap(string) = null; + var current_dep_type: ?DependencyType = null; + + while (lines.next()) |line_| { + const line = std.mem.trimRight(u8, line_, " \r\t"); + if (line.len == 0 or line[0] == '#') continue; + + var indent: usize = 0; + while (indent < line.len and line[indent] == ' ') indent += 1; + + const trimmed = strings.trim(line[indent..], " \r\t"); + if (trimmed.len == 0) continue; + + if (indent == 0 and strings.endsWithComptime(trimmed, ":")) { + if (current_entry) |*entry| { + entry.dependencies = current_deps; + entry.optionalDependencies = current_optional_deps; + entry.peerDependencies = current_peer_deps; + entry.devDependencies = current_dev_deps; + try self.consolidateAndAppendEntry(entry.*); + } + + current_specs.clearRetainingCapacity(); + const specs_str = trimmed[0 .. trimmed.len - 1]; + var specs_it = strings.split(specs_str, ","); + while (specs_it.next()) |spec| { + const spec_trimmed = strings.trim(spec, " \""); + try current_specs.append(try self.allocator.dupe(u8, spec_trimmed)); + } + + current_entry = Entry{ + .specs = try self.allocator.dupe([]const u8, current_specs.items), + .version = undefined, + }; + + for (current_specs.items) |spec| { + if (strings.indexOf(spec, "@file:")) |at_index| { + const file_path = spec[at_index + 6 ..]; + current_entry.?.file = try self.allocator.dupe(u8, file_path); + break; + } + } + + current_deps = null; + current_optional_deps = null; + current_peer_deps = null; + current_dev_deps = null; + current_dep_type = null; + continue; + } + + if (current_entry == null) continue; + + if (indent > 0) { + if (strings.eqlComptime(trimmed, "dependencies:")) { + current_dep_type = .production; + current_deps = bun.StringHashMap(string).init(self.allocator); + continue; + } + + if (strings.eqlComptime(trimmed, "optionalDependencies:")) { + current_dep_type = .optional; + current_optional_deps = bun.StringHashMap(string).init(self.allocator); + continue; + } + + if (strings.eqlComptime(trimmed, "peerDependencies:")) { + current_dep_type = .peer; + current_peer_deps = bun.StringHashMap(string).init(self.allocator); + continue; + } + + if (strings.eqlComptime(trimmed, "devDependencies:")) { + current_dep_type = .development; + current_dev_deps = bun.StringHashMap(string).init(self.allocator); + continue; + } + + if (current_dep_type) |dep_type| { + if (strings.indexOf(trimmed, " ")) |space_idx| { + const key = strings.trim(trimmed[0..space_idx], " \""); + const value = strings.trim(trimmed[space_idx + 1 ..], " \""); + const map = switch (dep_type) { + .production => ¤t_deps.?, + .optional => ¤t_optional_deps.?, + .peer => ¤t_peer_deps.?, + .development => ¤t_dev_deps.?, + }; + try map.put(key, value); + } + continue; + } + + if (strings.indexOf(trimmed, " ")) |space_idx| { + const key = strings.trim(trimmed[0..space_idx], " "); + const value = strings.trim(trimmed[space_idx + 1 ..], " \""); + + if (strings.eqlComptime(key, "version")) { + current_entry.?.version = value; + + if (Entry.isWorkspaceDependency(value)) { + current_entry.?.workspace = true; + } else if (Entry.isFileDependency(value)) { + current_entry.?.file = if (strings.hasPrefixComptime(value, "file:") and value.len > "file:".len) value["file:".len..] else value; + } else if (Entry.isGitDependency(value)) { + const git_info = try Entry.parseGitUrl(self, value); + current_entry.?.resolved = git_info.url; + current_entry.?.commit = git_info.commit; + if (git_info.repo) |repo_name| { + current_entry.?.git_repo_name = try self.allocator.dupe(u8, repo_name); + } + } else if (Entry.isNpmAlias(value)) { + const alias_info = Entry.parseNpmAlias(value); + current_entry.?.version = alias_info.version; + } else if (Entry.isRemoteTarball(value)) { + current_entry.?.resolved = value; + } + } else if (strings.eqlComptime(key, "resolved")) { + current_entry.?.resolved = value; + if (Entry.isGitDependency(value)) { + const git_info = try Entry.parseGitUrl(self, value); + current_entry.?.resolved = git_info.url; + current_entry.?.commit = git_info.commit; + if (git_info.repo) |repo_name| { + current_entry.?.git_repo_name = try self.allocator.dupe(u8, repo_name); + } + } + } else if (strings.eqlComptime(key, "integrity")) { + current_entry.?.integrity = value; + } else if (strings.eqlComptime(key, "os")) { + var os_list = std.ArrayList([]const u8).init(self.allocator); + var os_it = strings.split(value[1 .. value.len - 1], ","); + while (os_it.next()) |os| { + const trimmed_os = strings.trim(os, " \""); + try os_list.append(trimmed_os); + } + current_entry.?.os = try os_list.toOwnedSlice(); + } else if (strings.eqlComptime(key, "cpu")) { + var cpu_list = std.ArrayList([]const u8).init(self.allocator); + var cpu_it = strings.split(value[1 .. value.len - 1], ","); + while (cpu_it.next()) |cpu| { + const trimmed_cpu = strings.trim(cpu, " \""); + try cpu_list.append(trimmed_cpu); + } + current_entry.?.cpu = try cpu_list.toOwnedSlice(); + } + } + } + } + + if (current_entry) |*entry| { + entry.dependencies = current_deps; + entry.optionalDependencies = current_optional_deps; + entry.peerDependencies = current_peer_deps; + entry.devDependencies = current_dev_deps; + try self.consolidateAndAppendEntry(entry.*); + } + } + + fn findEntryBySpec(self: *YarnLock, spec: []const u8) ?*Entry { + for (self.entries.items) |*entry| { + for (entry.specs) |entry_spec| { + if (strings.eql(entry_spec, spec)) { + return entry; + } + } + } + return null; + } + + fn consolidateAndAppendEntry(self: *YarnLock, new_entry: Entry) !void { + if (new_entry.specs.len == 0) return; + const package_name = Entry.getNameFromSpec(new_entry.specs[0]); + + for (self.entries.items) |*existing_entry| { + if (existing_entry.specs.len == 0) continue; + const existing_name = Entry.getNameFromSpec(existing_entry.specs[0]); + + if (strings.eql(package_name, existing_name) and + strings.eql(new_entry.version, existing_entry.version)) + { + const old_specs = existing_entry.specs; + const combined_specs = try self.allocator.alloc([]const u8, old_specs.len + new_entry.specs.len); + @memcpy(combined_specs[0..old_specs.len], old_specs); + @memcpy(combined_specs[old_specs.len..], new_entry.specs); + + self.allocator.free(old_specs); + existing_entry.specs = combined_specs; + + self.allocator.free(new_entry.specs); + return; + } + } + + try self.entries.append(new_entry); + } +}; + +const DependencyType = enum { + production, + development, + optional, + peer, +}; +const processDeps = struct { + fn process( + deps: bun.StringHashMap(string), + dep_type: DependencyType, + yarn_lock_: *YarnLock, + string_buf_: *Semver.String.Buf, + deps_buf: []Dependency, + res_buf: []Install.PackageID, + log: *logger.Log, + manager: *Install.PackageManager, + yarn_entry_to_package_id: []const Install.PackageID, + ) ![]Install.PackageID { + var deps_it = deps.iterator(); + var count: usize = 0; + var dep_spec_name_stack = std.heap.stackFallback(1024, bun.default_allocator); + const temp_allocator = dep_spec_name_stack.get(); + + while (deps_it.next()) |dep| { + const dep_name = dep.key_ptr.*; + const dep_version = dep.value_ptr.*; + const dep_spec = try std.fmt.allocPrint( + temp_allocator, + "{s}@{s}", + .{ dep_name, dep_version }, + ); + defer temp_allocator.free(dep_spec); + + if (yarn_lock_.findEntryBySpec(dep_spec)) |dep_entry| { + const dep_name_hash = stringHash(dep_name); + const dep_name_str = try string_buf_.appendWithHash(dep_name, dep_name_hash); + + const parsed_version = if (YarnLock.Entry.isNpmAlias(dep_version)) blk: { + const alias_info = YarnLock.Entry.parseNpmAlias(dep_version); + break :blk alias_info.version; + } else dep_version; + + deps_buf[count] = Dependency{ + .name = dep_name_str, + .name_hash = dep_name_hash, + .version = Dependency.parse( + yarn_lock_.allocator, + dep_name_str, + dep_name_hash, + parsed_version, + &Semver.SlicedString.init(parsed_version, parsed_version), + log, + manager, + ) orelse Dependency.Version{}, + .behavior = .{ + .prod = dep_type == .production, + .optional = dep_type == .optional, + .dev = dep_type == .development, + .peer = dep_type == .peer, + .workspace = dep_entry.workspace, + }, + }; + var found_package_id: ?Install.PackageID = null; + outer: for (yarn_lock_.entries.items, 0..) |entry_, yarn_idx| { + for (entry_.specs) |entry_spec| { + if (strings.eql(entry_spec, dep_spec)) { + found_package_id = yarn_entry_to_package_id[yarn_idx]; + break :outer; + } + } + } + + if (found_package_id) |pkg_id| { + res_buf[count] = pkg_id; + count += 1; + } + } + } + return res_buf[0..count]; + } +}.process; + +pub fn migrateYarnLockfile( + this: *Lockfile, + manager: *Install.PackageManager, + allocator: Allocator, + log: *logger.Log, + data: string, + dir: bun.FD, +) !LoadResult { + // todo yarn v2+ support + if (!strings.containsComptime(data, "# yarn lockfile v1")) { + return error.UnsupportedYarnLockfileVersion; + } + + var yarn_lock = YarnLock.init(allocator); + defer yarn_lock.deinit(); + + try yarn_lock.parse(data); + + this.initEmpty(allocator); + Install.initializeStore(); + + var string_buf = this.stringBuf(); + + var num_deps: u32 = 0; + var root_dep_count: u32 = 0; + var root_dep_count_from_package_json: u32 = 0; + + var root_dependencies = std.ArrayList(struct { name: []const u8, version: []const u8, dep_type: DependencyType }).init(allocator); + defer { + for (root_dependencies.items) |dep| { + allocator.free(dep.name); + allocator.free(dep.version); + } + root_dependencies.deinit(); + } + + { + // read package.json to get specified dependencies + const package_json_fd = bun.sys.File.openat(dir, "package.json", bun.O.RDONLY, 0).unwrap() catch return error.InvalidPackageJSON; + defer package_json_fd.close(); + const package_json_contents = package_json_fd.readToEnd(allocator).unwrap() catch return error.InvalidPackageJSON; + defer allocator.free(package_json_contents); + + const package_json_source = brk: { + var package_json_path_buf: bun.PathBuffer = undefined; + const package_json_path = bun.getFdPath(package_json_fd.handle, &package_json_path_buf) catch return error.InvalidPackageJSON; + break :brk logger.Source.initPathString(package_json_path, package_json_contents); + }; + const package_json_expr = JSON.parsePackageJSONUTF8WithOpts( + &package_json_source, + log, + allocator, + .{ + .is_json = true, + .allow_comments = true, + .allow_trailing_commas = true, + .guess_indentation = true, + }, + ) catch return error.InvalidPackageJSON; + + const package_json = package_json_expr.root; + + const package_name: ?[]const u8 = blk: { + if (package_json.asProperty("name")) |name_prop| { + if (name_prop.expr.data == .e_string) { + const name_slice = name_prop.expr.data.e_string.string(allocator) catch ""; + if (name_slice.len > 0) { + break :blk try allocator.dupe(u8, name_slice); + } + } + } + break :blk null; + }; + defer if (package_name) |name| allocator.free(name); + const package_name_hash = if (package_name) |name| String.Builder.stringHash(name) else 0; + + const sections = [_]struct { key: []const u8, dep_type: DependencyType }{ + .{ .key = "dependencies", .dep_type = .production }, + .{ .key = "devDependencies", .dep_type = .development }, + .{ .key = "optionalDependencies", .dep_type = .optional }, + .{ .key = "peerDependencies", .dep_type = .peer }, + }; + for (sections) |section_info| { + const prop = package_json.asProperty(section_info.key) orelse continue; + if (prop.expr.data != .e_object) continue; + + for (prop.expr.data.e_object.properties.slice()) |p| { + const key = p.key orelse continue; + if (key.data != .e_string) continue; + + const name_slice = key.data.e_string.string(allocator) catch continue; + const value = p.value orelse continue; + if (value.data != .e_string) continue; + + const version_slice = value.data.e_string.string(allocator) catch continue; + if (version_slice.len == 0) continue; + + const name = try allocator.dupe(u8, name_slice); + const version = try allocator.dupe(u8, version_slice); + try root_dependencies.append(.{ + .name = name, + .version = version, + .dep_type = section_info.dep_type, + }); + root_dep_count_from_package_json += 1; + } + } + + root_dep_count = @max(root_dep_count_from_package_json, 10); + num_deps += root_dep_count; + + for (yarn_lock.entries.items) |entry| { + if (entry.dependencies) |deps| { + num_deps += @intCast(deps.count()); + } + if (entry.optionalDependencies) |deps| { + num_deps += @intCast(deps.count()); + } + if (entry.peerDependencies) |deps| { + num_deps += @intCast(deps.count()); + } + if (entry.devDependencies) |deps| { + num_deps += @intCast(deps.count()); + } + } + + const num_packages = @as(u32, @intCast(yarn_lock.entries.items.len + 1)); + + try this.buffers.dependencies.ensureTotalCapacity(allocator, num_deps); + try this.buffers.resolutions.ensureTotalCapacity(allocator, num_deps); + try this.packages.ensureTotalCapacity(allocator, num_packages); + try this.package_index.ensureTotalCapacity(num_packages); + + const root_name = if (package_name) |name| try string_buf.appendWithHash(name, package_name_hash) else try string_buf.append(""); + + try this.packages.append(allocator, Lockfile.Package{ + .name = root_name, + .name_hash = package_name_hash, + .resolution = Resolution.init(.{ .root = {} }), + .dependencies = .{}, + .resolutions = .{}, + .meta = .{ + .id = 0, + .origin = .local, + .arch = .all, + .os = .all, + .man_dir = String{}, + .has_install_script = .false, + .integrity = Integrity{}, + }, + .bin = Bin.init(), + .scripts = .{}, + }); + + if (package_json.asProperty("resolutions")) |resolutions| { + var root_package = this.packages.get(0); + var string_builder = this.stringBuilder(); + + if (resolutions.expr.data == .e_object) { + string_builder.cap += resolutions.expr.data.e_object.properties.len * 128; + } + if (string_builder.cap > 0) { + try string_builder.allocate(); + } + try this.overrides.parseAppend(manager, this, &root_package, log, &package_json_source, package_json, &string_builder); + this.packages.set(0, root_package); + } + } + + var dependencies_buf = this.buffers.dependencies.items.ptr[0..num_deps]; + var resolutions_buf = this.buffers.resolutions.items.ptr[0..num_deps]; + + var yarn_entry_to_package_id = try allocator.alloc(Install.PackageID, yarn_lock.entries.items.len); + defer allocator.free(yarn_entry_to_package_id); + + const VersionInfo = struct { + version: string, + package_id: Install.PackageID, + yarn_idx: usize, + }; + + var package_versions = bun.StringHashMap(VersionInfo).init(allocator); + defer package_versions.deinit(); + + var scoped_packages = bun.StringHashMap(std.ArrayList(VersionInfo)).init(allocator); + defer { + var it = scoped_packages.iterator(); + while (it.next()) |entry| { + entry.value_ptr.deinit(); + } + scoped_packages.deinit(); + } + + var next_package_id: Install.PackageID = 1; // 0 is root + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + var is_npm_alias = false; + var is_direct_url = false; + for (entry.specs) |spec| { + if (strings.contains(spec, "@npm:")) { + is_npm_alias = true; + break; + } + if (strings.contains(spec, "@https://") or strings.contains(spec, "@http://")) { + is_direct_url = true; + } + } + + const name = if (is_npm_alias and entry.resolved != null) + YarnLock.Entry.getPackageNameFromResolvedUrl(entry.resolved.?) orelse YarnLock.Entry.getNameFromSpec(entry.specs[0]) + else if (is_direct_url) + YarnLock.Entry.getNameFromSpec(entry.specs[0]) + else if (entry.git_repo_name) |repo_name| + repo_name + else + YarnLock.Entry.getNameFromSpec(entry.specs[0]); + const version = entry.version; + + if (package_versions.get(name)) |existing| { + if (!strings.eql(existing.version, version)) { + var list = scoped_packages.get(name) orelse std.ArrayList(VersionInfo).init(allocator); + + var found_existing = false; + var found_new = false; + for (list.items) |item| { + if (strings.eql(item.version, existing.version)) found_existing = true; + if (strings.eql(item.version, version)) found_new = true; + } + + if (!found_existing) { + try list.append(.{ + .yarn_idx = existing.yarn_idx, + .version = existing.version, + .package_id = existing.package_id, + }); + } + + if (!found_new) { + const package_id = next_package_id; + next_package_id += 1; + try list.append(.{ + .yarn_idx = yarn_idx, + .version = version, + .package_id = package_id, + }); + yarn_entry_to_package_id[yarn_idx] = package_id; + } else { + for (list.items) |item| { + if (strings.eql(item.version, version)) { + yarn_entry_to_package_id[yarn_idx] = item.package_id; + break; + } + } + } + + try scoped_packages.put(name, list); + } else { + yarn_entry_to_package_id[yarn_idx] = existing.package_id; + } + } else { + const package_id = next_package_id; + next_package_id += 1; + yarn_entry_to_package_id[yarn_idx] = package_id; + try package_versions.put(name, .{ + .version = version, + .package_id = package_id, + .yarn_idx = yarn_idx, + }); + } + } + + var package_id_to_yarn_idx = try allocator.alloc(usize, next_package_id); + defer allocator.free(package_id_to_yarn_idx); + @memset(package_id_to_yarn_idx, std.math.maxInt(usize)); + + var created_packages = bun.StringHashMap(bool).init(allocator); + defer created_packages.deinit(); + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + var is_npm_alias = false; + for (entry.specs) |spec| { + if (strings.contains(spec, "@npm:")) { + is_npm_alias = true; + break; + } + } + + var is_direct_url_dep = false; + for (entry.specs) |spec| { + if (strings.contains(spec, "@https://") or strings.contains(spec, "@http://")) { + is_direct_url_dep = true; + break; + } + } + + const base_name = if (is_npm_alias and entry.resolved != null) + YarnLock.Entry.getPackageNameFromResolvedUrl(entry.resolved.?) orelse YarnLock.Entry.getNameFromSpec(entry.specs[0]) + else + YarnLock.Entry.getNameFromSpec(entry.specs[0]); + const package_id = yarn_entry_to_package_id[yarn_idx]; + + if (package_id < package_id_to_yarn_idx.len and package_id_to_yarn_idx[package_id] != std.math.maxInt(usize)) { + continue; + } + + package_id_to_yarn_idx[package_id] = yarn_idx; + + const name_to_use = blk: { + if (entry.commit != null and entry.git_repo_name != null) { + break :blk entry.git_repo_name.?; + } else if (entry.resolved) |resolved| { + if (is_direct_url_dep or YarnLock.Entry.isRemoteTarball(resolved) or strings.endsWithComptime(resolved, ".tgz")) { + // https://registry.npmjs.org/package/-/package-version.tgz + if (strings.contains(resolved, "registry.npmjs.org/") or strings.contains(resolved, "registry.yarnpkg.com/")) { + if (strings.indexOf(resolved, "/-/")) |separator_idx| { + if (strings.indexOf(resolved, "registry.")) |registry_idx| { + const after_registry = resolved[registry_idx..]; + if (strings.indexOf(after_registry, "/")) |domain_slash| { + const package_start = registry_idx + domain_slash + 1; + const extracted_name = resolved[package_start..separator_idx]; + break :blk extracted_name; + } + } + } + } + break :blk base_name; + } + } + break :blk base_name; + }; + + const name_hash = stringHash(name_to_use); + + try this.packages.append(allocator, Lockfile.Package{ + .name = try string_buf.appendWithHash(name_to_use, name_hash), + .name_hash = name_hash, + .resolution = blk: { + if (entry.workspace) { + break :blk Resolution.init(.{ .workspace = try string_buf.append(base_name) }); + } else if (entry.file) |file| { + if (strings.endsWithComptime(file, ".tgz") or strings.endsWithComptime(file, ".tar.gz")) { + break :blk Resolution.init(.{ .local_tarball = try string_buf.append(file) }); + } else { + break :blk Resolution.init(.{ .folder = try string_buf.append(file) }); + } + } else if (entry.commit) |commit| { + if (entry.resolved) |resolved| { + var owner_str: []const u8 = ""; + var repo_str: []const u8 = resolved; + + if (strings.contains(resolved, "github.com/")) { + if (strings.indexOf(resolved, "github.com/")) |idx| { + const after_github = resolved[idx + "github.com/".len ..]; + if (strings.indexOf(after_github, "/")) |slash_idx| { + owner_str = after_github[0..slash_idx]; + repo_str = after_github[slash_idx + 1 ..]; + if (strings.endsWithComptime(repo_str, ".git")) { + repo_str = repo_str[0 .. repo_str.len - 4]; + } + } + } + } + + const actual_name = if (entry.git_repo_name) |repo_name| repo_name else repo_str; + + if (owner_str.len > 0 and repo_str.len > 0) { + break :blk Resolution.init(.{ + .github = .{ + .owner = try string_buf.append(owner_str), + .repo = try string_buf.append(repo_str), + .committish = try string_buf.append(commit[0..@min("github:".len, commit.len)]), + .resolved = String{}, + .package_name = try string_buf.append(actual_name), + }, + }); + } else { + break :blk Resolution.init(.{ + .git = .{ + .owner = try string_buf.append(owner_str), + .repo = try string_buf.append(repo_str), + .committish = try string_buf.append(commit), + .resolved = String{}, + .package_name = try string_buf.append(actual_name), + }, + }); + } + } + break :blk Resolution{}; + } else if (entry.resolved) |resolved| { + if (is_direct_url_dep) { + break :blk Resolution.init(.{ + .remote_tarball = try string_buf.append(resolved), + }); + } + + if (YarnLock.Entry.isRemoteTarball(resolved)) { + break :blk Resolution.init(.{ + .remote_tarball = try string_buf.append(resolved), + }); + } else if (strings.endsWithComptime(resolved, ".tgz")) { + break :blk Resolution.init(.{ + .remote_tarball = try string_buf.append(resolved), + }); + } + + const version = entry.version; + const sliced_version = Semver.SlicedString.init(version, version); + const result = Semver.Version.parse(sliced_version); + if (!result.valid) { + break :blk Resolution{}; + } + + const is_default_registry = strings.hasPrefixComptime(resolved, "https://registry.yarnpkg.com/") or + strings.hasPrefixComptime(resolved, "https://registry.npmjs.org/"); + + const url = if (is_default_registry) String{} else try string_buf.append(resolved); + + break :blk Resolution.init(.{ + .npm = .{ + .url = url, + .version = result.version.min(), + }, + }); + } else { + break :blk Resolution{}; + } + }, + .dependencies = .{}, + .resolutions = .{}, + .meta = .{ + .id = package_id, + .origin = .npm, + .arch = if (entry.cpu) |cpu_list| arch: { + var arch = Npm.Architecture.none.negatable(); + for (cpu_list) |cpu| { + arch.apply(cpu); + } + break :arch arch.combine(); + } else .all, + .os = if (entry.os) |os_list| os: { + var os = Npm.OperatingSystem.none.negatable(); + for (os_list) |os_str| { + os.apply(os_str); + } + break :os os.combine(); + } else .all, + .man_dir = String{}, + .has_install_script = .false, + .integrity = if (entry.integrity) |integrity| + Integrity.parse(integrity) + else + Integrity{}, + }, + .bin = Bin.init(), + .scripts = .{}, + }); + } + + var dependencies_list = this.packages.items(.dependencies); + var resolution_list = this.packages.items(.resolutions); + + var actual_root_dep_count: u32 = 0; + + if (root_dependencies.items.len > 0) { + for (root_dependencies.items) |dep| { + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep.name, dep.version }); + defer allocator.free(dep_spec); + + var found_idx: ?usize = null; + for (yarn_lock.entries.items, 0..) |entry, idx| { + for (entry.specs) |spec| { + if (strings.eql(spec, dep_spec)) { + found_idx = idx; + break; + } + } + if (found_idx != null) break; + } + + if (found_idx) |idx| { + const name_hash = stringHash(dep.name); + const dep_name_string = try string_buf.appendWithHash(dep.name, name_hash); + + dependencies_buf[actual_root_dep_count] = Dependency{ + .name = dep_name_string, + .name_hash = name_hash, + .version = Dependency.parse( + allocator, + dep_name_string, + name_hash, + dep.version, + &Semver.SlicedString.init(dep.version, dep.version), + log, + manager, + ) orelse Dependency.Version{}, + .behavior = .{ + .prod = dep.dep_type == .production, + .dev = dep.dep_type == .development, + .optional = dep.dep_type == .optional, + .peer = dep.dep_type == .peer, + .workspace = false, + }, + }; + + resolutions_buf[actual_root_dep_count] = yarn_entry_to_package_id[idx]; + actual_root_dep_count += 1; + } + } + } + + dependencies_list[0] = .{ + .off = 0, + .len = actual_root_dep_count, + }; + resolution_list[0] = .{ + .off = 0, + .len = actual_root_dep_count, + }; + + dependencies_buf = dependencies_buf[actual_root_dep_count..]; + resolutions_buf = resolutions_buf[actual_root_dep_count..]; + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + const package_id = yarn_entry_to_package_id[yarn_idx]; + if (package_id == Install.invalid_package_id) continue; + + const dependencies_start = dependencies_buf.ptr; + const resolutions_start = resolutions_buf.ptr; + if (entry.dependencies) |deps| { + const processed = try processDeps(deps, .production, &yarn_lock, &string_buf, dependencies_buf, resolutions_buf, log, manager, yarn_entry_to_package_id); + dependencies_buf = dependencies_buf[processed.len..]; + resolutions_buf = resolutions_buf[processed.len..]; + } + + if (entry.optionalDependencies) |deps| { + const processed = try processDeps(deps, .optional, &yarn_lock, &string_buf, dependencies_buf, resolutions_buf, log, manager, yarn_entry_to_package_id); + dependencies_buf = dependencies_buf[processed.len..]; + resolutions_buf = resolutions_buf[processed.len..]; + } + + if (entry.peerDependencies) |deps| { + const processed = try processDeps(deps, .peer, &yarn_lock, &string_buf, dependencies_buf, resolutions_buf, log, manager, yarn_entry_to_package_id); + dependencies_buf = dependencies_buf[processed.len..]; + resolutions_buf = resolutions_buf[processed.len..]; + } + + if (entry.devDependencies) |deps| { + const processed = try processDeps(deps, .development, &yarn_lock, &string_buf, dependencies_buf, resolutions_buf, log, manager, yarn_entry_to_package_id); + dependencies_buf = dependencies_buf[processed.len..]; + resolutions_buf = resolutions_buf[processed.len..]; + } + + const deps_len = @intFromPtr(dependencies_buf.ptr) - @intFromPtr(dependencies_start); + const deps_off = @intFromPtr(dependencies_start) - @intFromPtr(this.buffers.dependencies.items.ptr); + dependencies_list[package_id] = .{ + .off = @intCast(deps_off / @sizeOf(Dependency)), + .len = @intCast(deps_len / @sizeOf(Dependency)), + }; + resolution_list[package_id] = .{ + .off = @intCast((@intFromPtr(resolutions_start) - @intFromPtr(this.buffers.resolutions.items.ptr)) / @sizeOf(Install.PackageID)), + .len = @intCast((@intFromPtr(resolutions_buf.ptr) - @intFromPtr(resolutions_start)) / @sizeOf(Install.PackageID)), + }; + } + + this.buffers.dependencies.items.len = @intCast((@intFromPtr(dependencies_buf.ptr) - @intFromPtr(this.buffers.dependencies.items.ptr)) / @sizeOf(Dependency)); + this.buffers.resolutions.items.len = this.buffers.dependencies.items.len; + + try this.buffers.hoisted_dependencies.ensureTotalCapacity(allocator, this.buffers.dependencies.items.len * 2); + + try this.buffers.trees.append(allocator, Tree{ + .id = 0, + .parent = Tree.invalid_id, + .dependency_id = Tree.root_dep_id, + .dependencies = .{ + .off = 0, + .len = 0, + }, + }); + + var package_dependents = try allocator.alloc(std.ArrayList(Install.PackageID), next_package_id); + defer { + for (package_dependents) |*list| { + list.deinit(); + } + allocator.free(package_dependents); + } + for (package_dependents) |*list| { + list.* = std.ArrayList(Install.PackageID).init(allocator); + } + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + const parent_package_id = yarn_entry_to_package_id[yarn_idx]; + + const dep_maps = [_]?bun.StringHashMap(string){ + entry.dependencies, + entry.optionalDependencies, + entry.peerDependencies, + entry.devDependencies, + }; + + for (dep_maps) |maybe_deps| { + if (maybe_deps) |deps| { + var deps_it = deps.iterator(); + while (deps_it.next()) |dep| { + const dep_name = dep.key_ptr.*; + const dep_version = dep.value_ptr.*; + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep_name, dep_version }); + defer allocator.free(dep_spec); + + if (yarn_lock.findEntryBySpec(dep_spec)) |dep_entry| { + for (yarn_lock.entries.items, 0..) |*e, idx| { + var found = false; + for (e.specs) |spec| { + for (dep_entry.specs) |dep_spec_item| { + if (strings.eql(spec, dep_spec_item)) { + found = true; + break; + } + } + if (found) break; + } + + if (found) { + const dep_package_id = yarn_entry_to_package_id[idx]; + try package_dependents[dep_package_id].append(parent_package_id); + break; + } + } + } + } + } + } + } + + for (root_dependencies.items) |dep| { + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep.name, dep.version }); + defer allocator.free(dep_spec); + + for (yarn_lock.entries.items, 0..) |entry, idx| { + for (entry.specs) |spec| { + if (strings.eql(spec, dep_spec)) { + const dep_package_id = yarn_entry_to_package_id[idx]; + try package_dependents[dep_package_id].append(0); // 0 is root package + break; + } + } + } + } + + var packages_slice = this.packages.slice(); + + var scoped_it = scoped_packages.iterator(); + while (scoped_it.next()) |entry| { + const base_name = entry.key_ptr.*; + const versions = entry.value_ptr.*; + + std.sort.pdq(VersionInfo, versions.items, {}, struct { + fn lessThan(_: void, a: VersionInfo, b: VersionInfo) bool { + return a.package_id < b.package_id; + } + }.lessThan); + + const original_name_hash = stringHash(base_name); + if (this.package_index.getPtr(original_name_hash)) |original_entry| { + switch (original_entry.*) { + .id => { + _ = this.package_index.remove(original_name_hash); + }, + .ids => |*existing_ids| { + existing_ids.deinit(this.allocator); + _ = this.package_index.remove(original_name_hash); + }, + } + } else {} + } + + var final_check_it = scoped_packages.iterator(); + while (final_check_it.next()) |entry| { + const base_name = entry.key_ptr.*; + const versions = entry.value_ptr.*; + + for (versions.items) |version_info| { + const package_id = version_info.package_id; + + var found_in_index = false; + var check_it = this.package_index.iterator(); + while (check_it.next()) |index_entry| { + switch (index_entry.value_ptr.*) { + .id => |id| { + if (id == package_id) { + found_in_index = true; + break; + } + }, + .ids => |ids| { + for (ids.items) |id| { + if (id == package_id) { + found_in_index = true; + break; + } + } + if (found_in_index) break; + }, + } + } + + if (!found_in_index) { + const fallback_name = try std.fmt.allocPrint(allocator, "{s}#{}", .{ base_name, package_id }); + defer allocator.free(fallback_name); + + const fallback_hash = stringHash(fallback_name); + try this.getOrPutID(package_id, fallback_hash); + } + } + } + + var package_names = try allocator.alloc([]const u8, next_package_id); + defer allocator.free(package_names); + @memset(package_names, ""); + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + const package_id = yarn_entry_to_package_id[yarn_idx]; + if (package_names[package_id].len == 0) { + package_names[package_id] = YarnLock.Entry.getNameFromSpec(entry.specs[0]); + } + } + + var root_packages = bun.StringHashMap(PackageID).init(allocator); + defer root_packages.deinit(); + + var usage_count = bun.StringHashMap(u32).init(allocator); + defer usage_count.deinit(); + for (yarn_lock.entries.items, 0..) |_, entry_idx| { + const package_id = yarn_entry_to_package_id[entry_idx]; + if (package_id == Install.invalid_package_id) continue; + const base_name = package_names[package_id]; + + for (yarn_lock.entries.items) |dep_entry| { + if (dep_entry.dependencies) |deps| { + var deps_iter = deps.iterator(); + while (deps_iter.next()) |dep| { + if (strings.eql(dep.key_ptr.*, base_name)) { + const count = usage_count.get(base_name) orelse 0; + try usage_count.put(base_name, count + 1); + } + } + } + } + } + + for (yarn_lock.entries.items, 0..) |_, entry_idx| { + const package_id = yarn_entry_to_package_id[entry_idx]; + if (package_id == Install.invalid_package_id) continue; + const base_name = package_names[package_id]; + + if (root_packages.get(base_name) == null) { + try root_packages.put(base_name, package_id); + const name_hash = stringHash(base_name); + try this.getOrPutID(package_id, name_hash); + } + } + + var scoped_names = std.AutoHashMap(PackageID, []const u8).init(allocator); + defer scoped_names.deinit(); + var scoped_count: u32 = 0; + for (yarn_lock.entries.items, 0..) |_, entry_idx| { + const package_id = yarn_entry_to_package_id[entry_idx]; + if (package_id == Install.invalid_package_id) continue; + const base_name = package_names[package_id]; + + if (root_packages.get(base_name)) |root_pkg_id| { + if (root_pkg_id == package_id) { + continue; + } + } else { + continue; + } + + var scoped_name: ?[]const u8 = null; + for (yarn_lock.entries.items, 0..) |dep_entry, dep_entry_idx| { + const dep_package_id = yarn_entry_to_package_id[dep_entry_idx]; + if (dep_package_id == Install.invalid_package_id) continue; + + if (dep_entry.dependencies) |deps| { + var deps_iter = deps.iterator(); + while (deps_iter.next()) |dep| { + if (strings.eql(dep.key_ptr.*, base_name)) { + if (dep_package_id != package_id) { + const parent_name = package_names[dep_package_id]; + + const potential_name = try std.fmt.allocPrint(allocator, "{s}/{s}", .{ parent_name, base_name }); + + var name_already_used = false; + var value_iter = scoped_names.valueIterator(); + while (value_iter.next()) |existing_name| { + if (strings.eql(existing_name.*, potential_name)) { + name_already_used = true; + break; + } + } + + if (!name_already_used) { + scoped_name = potential_name; + break; + } else { + allocator.free(potential_name); + } + } + } + } + if (scoped_name != null) break; + } + } + + if (scoped_name == null) { + const version_str = switch (this.packages.get(package_id).resolution.tag) { + .npm => brk: { + var version_buf: [64]u8 = undefined; + const formatted = std.fmt.bufPrint(&version_buf, "{}", .{this.packages.get(package_id).resolution.value.npm.version.fmt(this.buffers.string_bytes.items)}) catch ""; + break :brk formatted; + }, + else => "unknown", + }; + scoped_name = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ base_name, version_str }); + } + + if (scoped_name) |final_scoped_name| { + const name_hash = stringHash(final_scoped_name); + try this.getOrPutID(package_id, name_hash); + try scoped_names.put(package_id, final_scoped_name); + scoped_count += 1; + } + } + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + const package_id = yarn_entry_to_package_id[yarn_idx]; + if (package_id == Install.invalid_package_id) continue; + + if (entry.resolved) |resolved| { + if (YarnLock.Entry.getPackageNameFromResolvedUrl(resolved)) |real_name| { + for (entry.specs) |spec| { + const alias_name = YarnLock.Entry.getNameFromSpec(spec); + + if (!strings.eql(alias_name, real_name)) { + const alias_hash = stringHash(alias_name); + try this.getOrPutID(package_id, alias_hash); + } + } + } + } + } + + this.buffers.trees.items[0].dependencies = .{ .off = 0, .len = 0 }; + + var spec_to_package_id = bun.StringHashMap(Install.PackageID).init(allocator); + defer spec_to_package_id.deinit(); + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + const package_id = yarn_entry_to_package_id[yarn_idx]; + if (package_id == Install.invalid_package_id) continue; + + for (entry.specs) |spec| { + try spec_to_package_id.put(spec, package_id); + } + } + + const root_deps_off = @as(u32, @intCast(this.buffers.dependencies.items.len)); + const root_resolutions_off = @as(u32, @intCast(this.buffers.resolutions.items.len)); + + if (root_dependencies.items.len > 0) { + for (root_dependencies.items) |root_dep| { + _ = @as(DependencyID, @intCast(this.buffers.dependencies.items.len)); + + const name_hash = stringHash(root_dep.name); + const dep_name_string = try string_buf.appendWithHash(root_dep.name, name_hash); + const dep_version_string = try string_buf.append(root_dep.version); + const sliced_string = Semver.SlicedString.init(dep_version_string.slice(this.buffers.string_bytes.items), dep_version_string.slice(this.buffers.string_bytes.items)); + + var parsed_version = Dependency.parse( + allocator, + dep_name_string, + name_hash, + dep_version_string.slice(this.buffers.string_bytes.items), + &sliced_string, + log, + manager, + ) orelse Dependency.Version{}; + + parsed_version.literal = dep_version_string; + + const dep = Dependency{ + .name_hash = name_hash, + .name = dep_name_string, + .version = parsed_version, + .behavior = .{ + .prod = root_dep.dep_type == .production, + .dev = root_dep.dep_type == .development, + .optional = root_dep.dep_type == .optional, + .peer = root_dep.dep_type == .peer, + .workspace = false, + }, + }; + + try this.buffers.dependencies.append(allocator, dep); + + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ root_dep.name, root_dep.version }); + defer allocator.free(dep_spec); + + if (spec_to_package_id.get(dep_spec)) |pkg_id| { + try this.buffers.resolutions.append(allocator, pkg_id); + } else { + try this.buffers.resolutions.append(allocator, Install.invalid_package_id); + } + } + } + + packages_slice.items(.dependencies)[0] = .{ + .off = root_deps_off, + .len = @as(u32, @intCast(root_dependencies.items.len)), + }; + packages_slice.items(.resolutions)[0] = .{ + .off = root_resolutions_off, + .len = @as(u32, @intCast(root_dependencies.items.len)), + }; + + for (yarn_lock.entries.items, 0..) |entry, yarn_idx| { + const package_id = yarn_entry_to_package_id[yarn_idx]; + if (package_id == Install.invalid_package_id) continue; + + var dep_count: u32 = 0; + const deps_off = @as(u32, @intCast(this.buffers.dependencies.items.len)); + const resolutions_off = @as(u32, @intCast(this.buffers.resolutions.items.len)); + + if (entry.dependencies) |deps| { + var dep_iter = deps.iterator(); + while (dep_iter.next()) |dep_entry| { + const dep_name = dep_entry.key_ptr.*; + const dep_version_literal = dep_entry.value_ptr.*; + + const name_hash = stringHash(dep_name); + const dep_name_string = try string_buf.appendWithHash(dep_name, name_hash); + const dep_version_string = try string_buf.append(dep_version_literal); + const sliced_string = Semver.SlicedString.init(dep_version_string.slice(this.buffers.string_bytes.items), dep_version_string.slice(this.buffers.string_bytes.items)); + + var parsed_version = Dependency.parse( + allocator, + dep_name_string, + name_hash, + dep_version_string.slice(this.buffers.string_bytes.items), + &sliced_string, + log, + manager, + ) orelse Dependency.Version{}; + + parsed_version.literal = dep_version_string; + + try this.buffers.dependencies.append(allocator, Dependency{ + .name = dep_name_string, + .name_hash = name_hash, + .version = parsed_version, + .behavior = .{ .prod = true }, + }); + + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep_name, dep_version_literal }); + defer allocator.free(dep_spec); + + if (spec_to_package_id.get(dep_spec)) |res_pkg_id| { + try this.buffers.resolutions.append(allocator, res_pkg_id); + } else { + try this.buffers.resolutions.append(allocator, Install.invalid_package_id); + } + + dep_count += 1; + } + } + + if (entry.optionalDependencies) |optional_deps| { + var opt_dep_iter = optional_deps.iterator(); + while (opt_dep_iter.next()) |dep_entry| { + const dep_name = dep_entry.key_ptr.*; + const dep_version_literal = dep_entry.value_ptr.*; + + const name_hash = stringHash(dep_name); + const dep_name_string = try string_buf.appendWithHash(dep_name, name_hash); + + const dep_version_string = try string_buf.append(dep_version_literal); + const sliced_string = Semver.SlicedString.init(dep_version_string.slice(this.buffers.string_bytes.items), dep_version_string.slice(this.buffers.string_bytes.items)); + + var parsed_version = Dependency.parse( + allocator, + dep_name_string, + name_hash, + dep_version_string.slice(this.buffers.string_bytes.items), + &sliced_string, + log, + manager, + ) orelse Dependency.Version{}; + + parsed_version.literal = dep_version_string; + + try this.buffers.dependencies.append(allocator, Dependency{ + .name = dep_name_string, + .name_hash = name_hash, + .version = parsed_version, + .behavior = .{ .optional = true }, + }); + + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep_name, dep_version_literal }); + defer allocator.free(dep_spec); + + if (spec_to_package_id.get(dep_spec)) |res_pkg_id| { + try this.buffers.resolutions.append(allocator, res_pkg_id); + } else { + try this.buffers.resolutions.append(allocator, Install.invalid_package_id); + } + + dep_count += 1; + } + } + + if (entry.peerDependencies) |peer_deps| { + var peer_dep_iter = peer_deps.iterator(); + while (peer_dep_iter.next()) |dep_entry| { + const dep_name = dep_entry.key_ptr.*; + const dep_version_literal = dep_entry.value_ptr.*; + + const name_hash = stringHash(dep_name); + const dep_name_string = try string_buf.appendWithHash(dep_name, name_hash); + + const dep_version_string = try string_buf.append(dep_version_literal); + const sliced_string = Semver.SlicedString.init(dep_version_string.slice(this.buffers.string_bytes.items), dep_version_string.slice(this.buffers.string_bytes.items)); + + var parsed_version = Dependency.parse( + allocator, + dep_name_string, + name_hash, + dep_version_string.slice(this.buffers.string_bytes.items), + &sliced_string, + log, + manager, + ) orelse Dependency.Version{}; + + parsed_version.literal = dep_version_string; + + try this.buffers.dependencies.append(allocator, Dependency{ + .name = dep_name_string, + .name_hash = name_hash, + .version = parsed_version, + .behavior = .{ .peer = true }, + }); + + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep_name, dep_version_literal }); + defer allocator.free(dep_spec); + + if (spec_to_package_id.get(dep_spec)) |res_pkg_id| { + try this.buffers.resolutions.append(allocator, res_pkg_id); + } else { + try this.buffers.resolutions.append(allocator, Install.invalid_package_id); + } + + dep_count += 1; + } + } + + if (entry.devDependencies) |dev_deps| { + var dev_dep_iter = dev_deps.iterator(); + while (dev_dep_iter.next()) |dep_entry| { + const dep_name = dep_entry.key_ptr.*; + const dep_version_literal = dep_entry.value_ptr.*; + + const name_hash = stringHash(dep_name); + const dep_name_string = try string_buf.appendWithHash(dep_name, name_hash); + + const dep_version_string = try string_buf.append(dep_version_literal); + const sliced_string = Semver.SlicedString.init(dep_version_string.slice(this.buffers.string_bytes.items), dep_version_string.slice(this.buffers.string_bytes.items)); + + var parsed_version = Dependency.parse( + allocator, + dep_name_string, + name_hash, + dep_version_string.slice(this.buffers.string_bytes.items), + &sliced_string, + log, + manager, + ) orelse Dependency.Version{}; + + parsed_version.literal = dep_version_string; + + try this.buffers.dependencies.append(allocator, Dependency{ + .name = dep_name_string, + .name_hash = name_hash, + .version = parsed_version, + .behavior = .{ .dev = true }, + }); + + const dep_spec = try std.fmt.allocPrint(allocator, "{s}@{s}", .{ dep_name, dep_version_literal }); + defer allocator.free(dep_spec); + + if (spec_to_package_id.get(dep_spec)) |res_pkg_id| { + try this.buffers.resolutions.append(allocator, res_pkg_id); + } else { + try this.buffers.resolutions.append(allocator, Install.invalid_package_id); + } + + dep_count += 1; + } + } + + packages_slice.items(.dependencies)[package_id] = .{ + .off = deps_off, + .len = dep_count, + }; + + packages_slice.items(.resolutions)[package_id] = .{ + .off = resolutions_off, + .len = dep_count, + }; + } + + try this.resolve(log); + + if (Environment.allow_assert) { + try this.verifyData(); + } + + this.meta_hash = try this.generateMetaHash(false, this.packages.len); + + const result = LoadResult{ .ok = .{ + .lockfile = this, + .was_migrated = true, + .loaded_from_binary_lockfile = false, + .serializer_result = .{}, + .format = .binary, + } }; + + return result; +} + +const string = []const u8; + +const Dependency = @import("./dependency.zig"); +const Npm = @import("./npm.zig"); +const std = @import("std"); +const Bin = @import("./bin.zig").Bin; +const Integrity = @import("./integrity.zig").Integrity; +const Resolution = @import("./resolution.zig").Resolution; +const Allocator = std.mem.Allocator; + +const Semver = @import("../semver.zig"); +const String = Semver.String; +const stringHash = String.Builder.stringHash; + +const Install = @import("./install.zig"); +const DependencyID = Install.DependencyID; +const PackageID = Install.PackageID; + +const Lockfile = @import("./lockfile.zig"); +const LoadResult = Lockfile.LoadResult; +const Tree = Lockfile.Tree; + +const bun = @import("bun"); +const Environment = bun.Environment; +const JSON = bun.json; +const logger = bun.logger; +const strings = bun.strings; diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts index 9f60fb719d..24f0407ad5 100644 --- a/src/js/builtins.d.ts +++ b/src/js/builtins.d.ts @@ -65,7 +65,15 @@ declare function $extractHighWaterMarkFromQueuingStrategyInit(obj: any): any; * Overrides ** */ -interface ReadableStreamDefaultController extends _ReadableStreamDefaultController { +class ReadableStreamDefaultController extends _ReadableStreamDefaultController { + constructor( + stream: unknown, + underlyingSource: unknown, + size: unknown, + highWaterMark: unknown, + $isReadableStream: typeof $isReadableStream, + ); + $controlledReadableStream: ReadableStream; $underlyingSource: UnderlyingSource; $queue: any; @@ -605,15 +613,6 @@ declare class OutOfMemoryError { constructor(); } -declare class ReadableStreamDefaultController { - constructor( - stream: unknown, - underlyingSource: unknown, - size: unknown, - highWaterMark: unknown, - $isReadableStream: typeof $isReadableStream, - ); -} declare class ReadableByteStreamController { constructor( stream: unknown, diff --git a/src/js/builtins/ProcessObjectInternals.ts b/src/js/builtins/ProcessObjectInternals.ts index 16749f4adf..be8d1cf39c 100644 --- a/src/js/builtins/ProcessObjectInternals.ts +++ b/src/js/builtins/ProcessObjectInternals.ts @@ -91,21 +91,23 @@ export function getStdinStream( var reader: ReadableStreamDefaultReader | undefined; - var shouldUnref = false; + var shouldDisown = false; let needsInternalReadRefresh = false; + // if true, while the stream is own()ed it will not + let forceUnref = false; - function ref() { + function own() { $debug("ref();", reader ? "already has reader" : "getting reader"); reader ??= native.getReader(); - source.updateRef(true); - shouldUnref = false; + source.updateRef(forceUnref ? false : true); + shouldDisown = false; if (needsInternalReadRefresh) { needsInternalReadRefresh = false; internalRead(stream); } } - function unref() { + function disown() { $debug("unref();"); if (reader) { @@ -119,6 +121,7 @@ export function getStdinStream( // Releasing the lock is not possible as there are active reads // we will instead pretend we are unref'd, and release the lock once the reads are finished. + shouldDisown = true; source?.updateRef?.(false); } } else if (source) { @@ -144,7 +147,7 @@ export function getStdinStream( // Therefore the following hack is only specific to `process.stdin` // and does not apply to the underlying Stream implementation. if (event === "readable") { - ref(); + own(); } return originalOn.$call(this, event, listener); }; @@ -155,12 +158,14 @@ export function getStdinStream( // but we haven't made that work yet. Until then, we need to manually add some of net.Socket's methods if (isTTY || fdType !== BunProcessStdinFdType.file) { stream.ref = function () { - ref(); + forceUnref = false; + own(); return this; }; stream.unref = function () { - unref(); + forceUnref = true; + source?.updateRef?.(false); return this; }; } @@ -168,15 +173,13 @@ export function getStdinStream( const originalPause = stream.pause; stream.pause = function () { $debug("pause();"); - let r = originalPause.$call(this); - unref(); - return r; + return originalPause.$call(this); }; const originalResume = stream.resume; stream.resume = function () { $debug("resume();"); - ref(); + own(); return originalResume.$call(this); }; @@ -189,7 +192,7 @@ export function getStdinStream( if (value) { stream.push(value); - if (shouldUnref) unref(); + if (shouldDisown) disown(); } else { if (!stream_endEmitted) { stream_endEmitted = true; @@ -198,7 +201,7 @@ export function getStdinStream( if (!stream_destroyed) { stream_destroyed = true; stream.destroy(); - unref(); + disown(); } } } catch (err) { @@ -216,7 +219,7 @@ export function getStdinStream( function triggerRead(_size) { $debug("_read();", reader); - if (reader && !shouldUnref) { + if (reader && !shouldDisown) { internalRead(this); } else { // The stream has not been ref()ed yet. If it is ever ref()ed, @@ -229,7 +232,7 @@ export function getStdinStream( stream.on("resume", () => { if (stream.isPaused()) return; // fake resume $debug('on("resume");'); - ref(); + own(); stream._undestroy(); stream_destroyed = false; }); @@ -241,6 +244,7 @@ export function getStdinStream( if (!stream.readableFlowing) { stream._readableState.reading = false; } + disown(); }); }); @@ -249,7 +253,7 @@ export function getStdinStream( stream_destroyed = true; process.nextTick(() => { stream.destroy(); - unref(); + disown(); }); } }); diff --git a/src/js/internal/tls.ts b/src/js/internal/tls.ts index 65f2d1c6b1..f02c0edb93 100644 --- a/src/js/internal/tls.ts +++ b/src/js/internal/tls.ts @@ -1,11 +1,5 @@ const { isTypedArray, isArrayBuffer } = require("node:util/types"); -const DEFAULT_CIPHERS = - "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"; - -const DEFAULT_CIPHERS_LIST = DEFAULT_CIPHERS.split(":"); -const DEFAULT_CIPHERS_SET = new Set([...DEFAULT_CIPHERS_LIST.map(c => c.toLowerCase()), ...DEFAULT_CIPHERS_LIST]); - function isPemObject(obj: unknown): obj is { pem: unknown } { return $isObject(obj) && "pem" in obj; } @@ -54,24 +48,6 @@ function isValidTLSArray(obj: unknown) { return false; } -function validateCiphers(ciphers: string) { - const requested = ciphers.split(":"); - for (const r of requested) { - if (!DEFAULT_CIPHERS_SET.has(r)) { - throw $ERR_SSL_NO_CIPHER_MATCH(); - } - } -} - const VALID_TLS_ERROR_MESSAGE_TYPES = "string or an instance of Buffer, TypedArray, DataView, or BunFile"; -export { - DEFAULT_CIPHERS, - DEFAULT_CIPHERS_LIST, - DEFAULT_CIPHERS_SET, - VALID_TLS_ERROR_MESSAGE_TYPES, - isValidTLSArray, - isValidTLSItem, - throwOnInvalidTLSArray, - validateCiphers, -}; +export { VALID_TLS_ERROR_MESSAGE_TYPES, isValidTLSArray, isValidTLSItem, throwOnInvalidTLSArray }; diff --git a/src/js/node/http2.ts b/src/js/node/http2.ts index 492f4d5338..93d23062c3 100644 --- a/src/js/node/http2.ts +++ b/src/js/node/http2.ts @@ -3789,7 +3789,7 @@ class Http2Server extends net.Server { options = {}; } options = initializeOptions(options); - super(options, connectionListener); + super(options); this[kSessions] = new SafeSet(); this.setMaxListeners(0); @@ -3800,6 +3800,14 @@ class Http2Server extends net.Server { } } + emit(event: string, ...args: any[]) { + if (event === "connection") { + // TODO: implement this at net/tls level to allow to inject socket in the server + // this works for now for Http2Server + super.prependOnceListener("connection", connectionListener); + } + return super.emit(event, ...args); + } setTimeout(ms, callback) { this.timeout = ms; if (typeof callback === "function") { diff --git a/src/js/node/net.ts b/src/js/node/net.ts index 48e55c8cdb..16b65d6cee 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -236,8 +236,11 @@ const SocketHandlers: SocketHandler = { open(socket) { const self = socket.data; if (!self) return; - socket.timeout(Math.ceil(self.timeout / 1000)); - + // make sure to disable timeout on usocket and handle on TS side + socket.timeout(0); + if (self.timeout) { + self.setTimeout(self.timeout); + } self._handle = socket; self.connecting = false; const options = self[bunTLSConnectOptions]; @@ -860,7 +863,11 @@ Object.defineProperty(Socket.prototype, "bytesWritten", { Socket.prototype[kAttach] = function (port, socket) { socket.data = this; socket[owner_symbol] = this; - socket.timeout(Math.ceil(this.timeout / 1000)); + if (this.timeout) { + this.setTimeout(this.timeout); + } + // make sure to disable timeout on usocket and handle on TS side + socket.timeout(0); this._handle = socket; this.connecting = false; @@ -1401,11 +1408,6 @@ Socket.prototype.setTimeout = { }, }.setTimeout; -Socket.prototype._onTimeout = function _onTimeout() { - $debug("_onTimeout"); - this.emit("timeout"); -}; - Socket.prototype._unrefTimer = function _unrefTimer() { for (let s = this; s !== null; s = s._parent) { if (s[kTimeout]) s[kTimeout].refresh(); @@ -1961,7 +1963,9 @@ function internalConnectMultipleTimeout(context, req, handle) { } function afterConnect(status, handle, req, readable, writable) { + if (!handle) return; const self = handle[owner_symbol]; + if (!self) return; // Callback may come after call to destroy if (self.destroyed) { diff --git a/src/js/node/tls.ts b/src/js/node/tls.ts index 10bfa3fad7..44b5c09c6c 100644 --- a/src/js/node/tls.ts +++ b/src/js/node/tls.ts @@ -4,7 +4,7 @@ const net = require("node:net"); const { Duplex } = require("node:stream"); const addServerName = $newZigFunction("Listener.zig", "jsAddServerName", 3); const { throwNotImplemented } = require("internal/shared"); -const { throwOnInvalidTLSArray, DEFAULT_CIPHERS, validateCiphers } = require("internal/tls"); +const { throwOnInvalidTLSArray } = require("internal/tls"); const { validateString } = require("internal/validators"); const { Server: NetServer, Socket: NetSocket } = net; @@ -13,6 +13,200 @@ const getBundledRootCertificates = $newCppFunction("NodeTLS.cpp", "getBundledRoo const getExtraCACertificates = $newCppFunction("NodeTLS.cpp", "getExtraCACertificates", 1); const canonicalizeIP = $newCppFunction("NodeTLS.cpp", "Bun__canonicalizeIP", 1); +const getTLSDefaultCiphers = $newCppFunction("NodeTLS.cpp", "getDefaultCiphers", 0); +const setTLSDefaultCiphers = $newCppFunction("NodeTLS.cpp", "setDefaultCiphers", 1); +let _VALID_CIPHERS_SET: Set | undefined; +function getValidCiphersSet() { + if (!_VALID_CIPHERS_SET) { + _VALID_CIPHERS_SET = new Set([ + "EXP1024-RC4-MD5", + "EXP1024-RC2-CBC-MD5", + "EXP1024-DES-CBC-SHA", + "EXP1024-DHE-DSS-DES-CBC-SHA", + "EXP1024-RC4-SHA", + "EXP1024-DHE-DSS-RC4-SHA", + "DHE-DSS-RC4-SHA", + + // AES ciphersuites from RFC 3268 + "AES128-SHA", + "DH-DSS-AES128-SHA", + "DH-RSA-AES128-SHA", + "DHE-DSS-AES128-SHA", + "DHE-RSA-AES128-SHA", + "ADH-AES128-SHA", + "AES256-SHA", + "DH-DSS-AES256-SHA", + "DH-RSA-AES256-SHA", + "DHE-DSS-AES256-SHA", + "DHE-RSA-AES256-SHA", + "ADH-AES256-SHA", + + // ECC ciphersuites from RFC 4492 + "ECDH-ECDSA-NULL-SHA", + "ECDH-ECDSA-RC4-SHA", + "ECDH-ECDSA-DES-CBC3-SHA", + "ECDH-ECDSA-AES128-SHA", + "ECDH-ECDSA-AES256-SHA", + "ECDHE-ECDSA-NULL-SHA", + "ECDHE-ECDSA-RC4-SHA", + "ECDHE-ECDSA-DES-CBC3-SHA", + "ECDHE-ECDSA-AES128-SHA", + "ECDHE-ECDSA-AES256-SHA", + + "ECDH-RSA-NULL-SHA", + "ECDH-RSA-RC4-SHA", + "ECDH-RSA-DES-CBC3-SHA", + "ECDH-RSA-AES128-SHA", + "ECDH-RSA-AES256-SHA", + "ECDHE-RSA-NULL-SHA", + "ECDHE-RSA-RC4-SHA", + "ECDHE-RSA-DES-CBC3-SHA", + "ECDHE-RSA-AES128-SHA", + "ECDHE-RSA-AES256-SHA", + "ECDHE-RSA-AES128-SHA256", + "AECDH-NULL-SHA", + "AECDH-RC4-SHA", + "AECDH-DES-CBC3-SHA", + "AECDH-AES128-SHA", + "AECDH-AES256-SHA", + + // PSK ciphersuites from RFC 4279 + "PSK-RC4-SHA", + "PSK-3DES-EDE-CBC-SHA", + "PSK-AES128-CBC-SHA", + "PSK-AES256-CBC-SHA", + + // PSK ciphersuites from RFC 5489 + "ECDHE-PSK-AES128-CBC-SHA", + "ECDHE-PSK-AES256-CBC-SHA", + + // SRP ciphersuite from RFC 5054 + "SRP-3DES-EDE-CBC-SHA", + "SRP-RSA-3DES-EDE-CBC-SHA", + "SRP-DSS-3DES-EDE-CBC-SHA", + "SRP-AES-128-CBC-SHA", + "SRP-RSA-AES-128-CBC-SHA", + "SRP-DSS-AES-128-CBC-SHA", + "SRP-AES-256-CBC-SHA", + "SRP-RSA-AES-256-CBC-SHA", + "SRP-DSS-AES-256-CBC-SHA", + + // Camellia ciphersuites from RFC 4132 + "CAMELLIA128-SHA", + "DH-DSS-CAMELLIA128-SHA", + "DH-RSA-CAMELLIA128-SHA", + "DHE-DSS-CAMELLIA128-SHA", + "DHE-RSA-CAMELLIA128-SHA", + "ADH-CAMELLIA128-SHA", + + "CAMELLIA256-SHA", + "DH-DSS-CAMELLIA256-SHA", + "DH-RSA-CAMELLIA256-SHA", + "DHE-DSS-CAMELLIA256-SHA", + "DHE-RSA-CAMELLIA256-SHA", + "ADH-CAMELLIA256-SHA", + + // SEED ciphersuites from RFC 4162 + "SEED-SHA", + "DH-DSS-SEED-SHA", + "DH-RSA-SEED-SHA", + "DHE-DSS-SEED-SHA", + "DHE-RSA-SEED-SHA", + "ADH-SEED-SHA", + + // TLS v1.2 ciphersuites + "NULL-SHA256", + "AES128-SHA256", + "AES256-SHA256", + "DH-DSS-AES128-SHA256", + "DH-RSA-AES128-SHA256", + "DHE-DSS-AES128-SHA256", + "DHE-RSA-AES128-SHA256", + "DH-DSS-AES256-SHA256", + "DH-RSA-AES256-SHA256", + "DHE-DSS-AES256-SHA256", + "DHE-RSA-AES256-SHA256", + "ADH-AES128-SHA256", + "ADH-AES256-SHA256", + + // TLS v1.2 GCM ciphersuites from RFC 5288 + "AES128-GCM-SHA256", + "AES256-GCM-SHA384", + "DHE-RSA-AES128-GCM-SHA256", + "DHE-RSA-AES256-GCM-SHA384", + "DH-RSA-AES128-GCM-SHA256", + "DH-RSA-AES256-GCM-SHA384", + "DHE-DSS-AES128-GCM-SHA256", + "DHE-DSS-AES256-GCM-SHA384", + "DH-DSS-AES128-GCM-SHA256", + "DH-DSS-AES256-GCM-SHA384", + "ADH-AES128-GCM-SHA256", + "ADH-AES256-GCM-SHA384", + + // ECDH HMAC based ciphersuites from RFC 5289 + + "ECDHE-ECDSA-AES128-SHA256", + "ECDHE-ECDSA-AES256-SHA384", + "ECDH-ECDSA-AES128-SHA256", + "ECDH-ECDSA-AES256-SHA384", + "ECDHE-RSA-AES128-SHA256", + "ECDHE-RSA-AES256-SHA384", + "ECDH-RSA-AES128-SHA256", + "ECDH-RSA-AES256-SHA384", + + // ECDH GCM based ciphersuites from RFC 5289 + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDH-ECDSA-AES128-GCM-SHA256", + "ECDH-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDH-RSA-AES128-GCM-SHA256", + "ECDH-RSA-AES256-GCM-SHA384", + "ECDHE-RSA-CHACHA20-POLY1305", + "ECDHE-ECDSA-CHACHA20-POLY1305", + "ECDHE-PSK-CHACHA20-POLY1305", + + // TLS 1.3 ciphersuites from RFC 8446. + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + + // Configurations include in the default cipher list + "HIGH", + "!aNULL", + "!eNULL", + "!EXPORT", + "!DES", + "!RC4", + "!MD5", + "!PSK", + "!SRP", + "!CAMELLIA", + ]); + } + return _VALID_CIPHERS_SET; +} + +function validateCiphers(ciphers: string, name: string = "options") { + // Set the cipher list and cipher suite before anything else because + // @SECLEVEL= changes the security level and that affects subsequent + // operations. + if (ciphers !== undefined && ciphers !== null) { + validateString(ciphers, `${name}.ciphers`); + + // TODO: right now we need this because we dont create the CTX before listening/connecting + // we need to change that in the future and let BoringSSL do the validation + const ciphersSet = getValidCiphersSet(); + const requested = ciphers.split(":"); + for (const r of requested) { + if (r && !ciphersSet.has(r)) { + throw $ERR_SSL_NO_CIPHER_MATCH(); + } + } + } +} + const SymbolReplace = Symbol.replace; const RegExpPrototypeSymbolReplace = RegExp.prototype[SymbolReplace]; const RegExpPrototypeExec = RegExp.prototype.exec; @@ -601,7 +795,7 @@ function Server(options, secureConnectionListener): void { validateCiphers(options.ciphers); - // TODO: Pass the ciphers + this.ciphers = options.ciphers; } } }; @@ -629,6 +823,7 @@ function Server(options, secureConnectionListener): void { clientRenegotiationLimit: CLIENT_RENEG_LIMIT, clientRenegotiationWindow: CLIENT_RENEG_WINDOW, contexts: contexts, + ciphers: this.ciphers, }, TLSSocket, ]; @@ -680,7 +875,7 @@ function connect(...args) { } function getCiphers() { - return DEFAULT_CIPHERS.split(":"); + return getDefaultCiphers().split(":"); } // Convert protocols array into valid OpenSSL protocols list @@ -783,6 +978,16 @@ function getCACertificates(type = "default") { } } +function tlsCipherFilter(a: string) { + return !a.startsWith("TLS_"); +} + +function getDefaultCiphers() { + // TLS_ will always be present until SSL_CTX_set_cipher_list is supported see default_ciphers.h + const ciphers = getTLSDefaultCiphers(); + return `TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256${ciphers ? ":" + ciphers : ""}`; +} + export default { CLIENT_RENEG_LIMIT, CLIENT_RENEG_WINDOW, @@ -790,7 +995,18 @@ export default { convertALPNProtocols, createSecureContext, createServer, - DEFAULT_CIPHERS, + get DEFAULT_CIPHERS() { + return getDefaultCiphers(); + }, + set DEFAULT_CIPHERS(value) { + if (value) { + validateCiphers(value, "value"); + // filter out TLS_ ciphers + const ciphers = value.split(":"); + value = ciphers.filter(tlsCipherFilter).join(":"); + } + setTLSDefaultCiphers(value); + }, DEFAULT_ECDH_CURVE, DEFAULT_MAX_VERSION, DEFAULT_MIN_VERSION, diff --git a/src/js_parser.zig b/src/js_parser.zig index a7c8601976..18b8ad94f9 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -4727,6 +4727,7 @@ pub const MacroState = struct { const Jest = struct { expect: Ref = Ref.None, + expectTypeOf: Ref = Ref.None, describe: Ref = Ref.None, @"test": Ref = Ref.None, it: Ref = Ref.None, @@ -6736,6 +6737,7 @@ fn NewParser_( p.jest.jest = try p.declareCommonJSSymbol(.unbound, "jest"); p.jest.it = try p.declareCommonJSSymbol(.unbound, "it"); p.jest.expect = try p.declareCommonJSSymbol(.unbound, "expect"); + p.jest.expectTypeOf = try p.declareCommonJSSymbol(.unbound, "expectTypeOf"); p.jest.beforeEach = try p.declareCommonJSSymbol(.unbound, "beforeEach"); p.jest.afterEach = try p.declareCommonJSSymbol(.unbound, "afterEach"); p.jest.beforeAll = try p.declareCommonJSSymbol(.unbound, "beforeAll"); diff --git a/src/js_printer.zig b/src/js_printer.zig index 5d304f8def..60c453a573 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -145,12 +145,6 @@ pub fn estimateLengthForUTF8(input: []const u8, comptime ascii_only: bool, compt return len; } -pub fn quoteForJSON(text: []const u8, output_: MutableString, comptime ascii_only: bool) !MutableString { - var bytes = output_; - try quoteForJSONBuffer(text, &bytes, ascii_only); - return bytes; -} - pub fn writePreQuotedString(text_in: []const u8, comptime Writer: type, writer: Writer, comptime quote_char: u8, comptime ascii_only: bool, comptime json: bool, comptime encoding: strings.Encoding) !void { const text = if (comptime encoding == .utf16) @as([]const u16, @alignCast(std.mem.bytesAsSlice(u16, text_in))) else text_in; if (comptime json and quote_char != '"') @compileError("for json, quote_char must be '\"'"); @@ -347,7 +341,7 @@ pub fn writePreQuotedString(text_in: []const u8, comptime Writer: type, writer: } } } -pub fn quoteForJSONBuffer(text: []const u8, bytes: *MutableString, comptime ascii_only: bool) !void { +pub fn quoteForJSON(text: []const u8, bytes: *MutableString, comptime ascii_only: bool) !void { const writer = bytes.writer(); try bytes.growIfNeeded(estimateLengthForUTF8(text, ascii_only, '"')); @@ -489,28 +483,14 @@ pub const RequireOrImportMeta = struct { }; pub const PrintResult = union(enum) { - result: struct { - code: []u8, - source_map: ?SourceMap.Chunk = null, - }, + result: Success, err: anyerror, - pub fn clone( - this: PrintResult, - allocator: std.mem.Allocator, - ) !PrintResult { - return switch (this) { - .result => PrintResult{ - .result = .{ - .code = try allocator.dupe(u8, this.result.code), - .source_map = this.result.source_map, - }, - }, - .err => PrintResult{ - .err = this.err, - }, - }; - } + pub const Success = struct { + code: []u8, + code_allocator: std.mem.Allocator, + source_map: ?SourceMap.Chunk = null, + }; }; // do not make this a packed struct @@ -5400,6 +5380,10 @@ pub fn NewWriter( return this.ctx.getMutableBuffer(); } + pub fn takeBuffer(this: *Self) MutableString { + return this.ctx.takeBuffer(); + } + pub fn slice(this: *Self) string { return this.ctx.slice(); } @@ -5504,6 +5488,11 @@ pub const BufferWriter = struct { return &this.buffer; } + pub fn takeBuffer(this: *BufferWriter) MutableString { + defer this.buffer = .initEmpty(this.buffer.allocator); + return this.buffer; + } + pub fn getWritten(this: *BufferWriter) []u8 { return this.buffer.list.items; } @@ -5808,11 +5797,13 @@ pub fn printAst( if (comptime FeatureFlags.runtime_transpiler_cache and generate_source_map) { if (opts.source_map_handler) |handler| { - const source_maps_chunk = printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()); + var source_maps_chunk = printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()); if (opts.runtime_transpiler_cache) |cache| { cache.put(printer.writer.ctx.getWritten(), source_maps_chunk.buffer.list.items); } + defer source_maps_chunk.deinit(); + try handler.onSourceMapChunk(source_maps_chunk, source); } else { if (opts.runtime_transpiler_cache) |cache| { @@ -5821,7 +5812,9 @@ pub fn printAst( } } else if (comptime generate_source_map) { if (opts.source_map_handler) |handler| { - try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source); + var chunk = printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()); + defer chunk.deinit(); + try handler.onSourceMapChunk(chunk, source); } } @@ -6011,9 +6004,12 @@ pub fn printWithWriterAndPlatform( break :brk chunk; } else null; + var buffer = printer.writer.takeBuffer(); + return .{ .result = .{ - .code = written, + .code = buffer.toOwnedSlice(), + .code_allocator = buffer.allocator, .source_map = source_map, }, }; @@ -6062,7 +6058,9 @@ pub fn printCommonJS( if (comptime generate_source_map) { if (opts.source_map_handler) |handler| { - try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source); + var chunk = printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()); + defer chunk.deinit(); + try handler.onSourceMapChunk(chunk, source); } } diff --git a/src/node-fallbacks/buffer.js b/src/node-fallbacks/buffer.js index 2d9e3c0f23..14bfb64d38 100644 --- a/src/node-fallbacks/buffer.js +++ b/src/node-fallbacks/buffer.js @@ -357,7 +357,7 @@ function fromObject(obj) { } if (obj.length !== undefined) { - if (typeof obj.length !== "number" || numberIsNaN(obj.length)) { + if (typeof obj.length !== "number" || Number.isNaN(obj.length)) { return createBuffer(0); } return fromArrayLike(obj); @@ -659,7 +659,7 @@ Buffer.prototype.equals = function equals(b) { Buffer.prototype.inspect = function inspect() { let str = ""; - const max = exports.INSPECT_MAX_BYTES; + const max = INSPECT_MAX_BYTES; str = this.toString("hex", 0, max) .replace(/(.{2})/g, "$1 ") .trim(); @@ -886,7 +886,7 @@ function hexWrite(buf, string, offset, length) { let i; for (i = 0; i < length; ++i) { const parsed = parseInt(string.substr(i * 2, 2), 16); - if (numberIsNaN(parsed)) return i; + if (Number.isNaN(parsed)) return i; buf[offset + i] = parsed; } return i; diff --git a/src/ptr/ref_count.zig b/src/ptr/ref_count.zig index a0a5acbf4c..0a2c0213f0 100644 --- a/src/ptr/ref_count.zig +++ b/src/ptr/ref_count.zig @@ -275,6 +275,10 @@ pub fn ThreadSafeRefCount(T: type, field_name: []const u8, destructor: fn (*T) v return counter.active_counts.load(.seq_cst) == 1; } + pub fn getCount(counter: *const @This()) u32 { + return counter.active_counts.load(.seq_cst); + } + pub fn dumpActiveRefs(count: *@This()) void { if (enable_debug) { const ptr: *T = @alignCast(@fieldParentPtr(field_name, count)); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index f3237e40ec..37448ea672 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -3755,7 +3755,6 @@ pub const Resolver = struct { } const dir_path = bun.strings.withoutTrailingSlashWindowsPath(Dirname.dirname(path)); - bun.strings.assertIsValidWindowsPath(u8, dir_path); const dir_entry: *Fs.FileSystem.RealFS.EntriesOption = rfs.readDirectory( dir_path, @@ -4224,7 +4223,6 @@ pub const Dirname = struct { const root = brk: { if (Environment.isWindows) { const root = ResolvePath.windowsFilesystemRoot(path); - assert(root.len > 0); // Preserve the trailing slash for UNC paths. // Going from `\\server\share\folder` should end up diff --git a/src/safety.zig b/src/safety.zig new file mode 100644 index 0000000000..54c5671f1e --- /dev/null +++ b/src/safety.zig @@ -0,0 +1,2 @@ +pub const AllocPtr = @import("./safety/alloc_ptr.zig").AllocPtr; +pub const CriticalSection = @import("./safety/CriticalSection.zig"); diff --git a/src/safety/CriticalSection.zig b/src/safety/CriticalSection.zig new file mode 100644 index 0000000000..3d3497503a --- /dev/null +++ b/src/safety/CriticalSection.zig @@ -0,0 +1,187 @@ +//! This type helps detect race conditions in debug/`ci_assert` builds. +//! +//! Store an instance of this type in or alongside shared data. Then, add the following to any +//! block of code that accesses the shared data: +//! +//! shared_data.critical_section.begin(); +//! defer shared_data.critical_section.end(); +//! // (do stuff with shared_data...) +//! +//! If a mutex is being used to ensure threads don't access the data simultaneously, call `begin` +//! *after* locking the mutex, and call `end` before releasing it, since it's the code that runs +//! when the mutex is held that needs to be prevented from concurrent execution. +//! +//! In code that only *reads* the shared data, and does not write to it, `beginReadOnly` can be +//! used instead. This allows multiple threads to read the data simultaneously, but will still +//! error if a thread tries to modify it (via calling `begin`). +//! +//! shared_data.critical_section.beginReadOnly(); +//! defer shared_data.critical_section.end(); +//! // (do *read-only* stuff with shared_data...) +//! +//! One use of this type could be to ensure that single-threaded containers aren't being used +//! concurrently without appropriate synchronization. For example, each method in an `ArrayList` +//! could start with a call to `begin` or `beginReadOnly` and end with a call to `end`. Then, an +//! `ArrayList` used by only one thread, or one used by multiple threads but synchronized via a +//! mutex, won't cause an error, but an `ArrayList` used by multiple threads concurrently without +//! synchronization, assuming at least one thread is modifying the data, will cause an error. + +const Self = @This(); + +internal_state: if (enabled) State else void = if (enabled) .{}, + +/// A value that does not alias any other thread ID. +/// See `Thread/Mutex/Recursive.zig` in the Zig standard library. +const invalid_thread_id = std.math.maxInt(Thread.Id); + +const OptionalThreadId = struct { + inner: Thread.Id, + + pub fn init(id: Thread.Id) OptionalThreadId { + return .{ .inner = id }; + } + + pub fn format( + self: OptionalThreadId, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = .{ fmt, options }; + if (self.inner == invalid_thread_id) { + try writer.writeAll("another thread"); + } else { + try writer.print("thread {}", .{self.inner}); + } + } +}; + +/// A reentrant lock that prevents multiple threads from accessing data at the same time, +/// except if all threads' use of the data is read-only. +const State = struct { + /// The ID of the thread that first acquired the lock (the "owner thread"). + thread_id: std.atomic.Value(Thread.Id) = .init(invalid_thread_id), + + /// Number of nested calls to `lockShared`/`lockExclusive` performed on the owner thread. + /// Only accessed on the owner thread. + owned_count: u32 = 0, + + /// Number of (possibly nested) calls to `lockShared` performed on any thread except the + /// owner thread. + count: std.atomic.Value(u32) = .init(0), + + /// If `count` is set to this value, it indicates that a thread has requested exclusive + /// (read/write) access. + const exclusive = std.math.maxInt(u32); + + /// Acquire the lock for shared (read-only) access. + fn lockShared(self: *State) void { + const current_id = Thread.getCurrentId(); + // .monotonic is okay because we don't need to synchronize-with other threads; we just need + // to make sure that only one thread succeeds in setting the value. + const id = self.thread_id.cmpxchgStrong( + invalid_thread_id, + current_id, + .monotonic, + .monotonic, + ) orelse current_id; + if (id == current_id) { + self.owned_count += 1; + } else if (self.count.fetchAdd(1, .monotonic) == exclusive) { + std.debug.panic( + "race condition: thread {} tried to read data being modified by {}", + .{ current_id, OptionalThreadId.init(id) }, + ); + } + } + + /// Acquire the lock for exclusive (read/write) access. + fn lockExclusive(self: *State) void { + const current_id = Thread.getCurrentId(); + // .monotonic is okay because we don't need to synchronize-with other threads; we just need + // to make sure that only one thread succeeds in setting the value. + const id = self.thread_id.cmpxchgStrong( + invalid_thread_id, + current_id, + .monotonic, + .monotonic, + ) orelse current_id; + if (id == current_id) { + // .monotonic is okay because concurrent access is an error. + switch (self.count.swap(exclusive, .monotonic)) { + 0, exclusive => {}, + else => std.debug.panic( + "race condition: thread {} tried to modify data being read by {}", + .{ current_id, OptionalThreadId.init(id) }, + ), + } + self.owned_count += 1; + } else { + std.debug.panic( + "race condition: thread {} tried to modify data being accessed by {}", + .{ current_id, OptionalThreadId.init(id) }, + ); + } + } + + /// Release the lock. + fn unlock(self: *State) void { + const current_id = Thread.getCurrentId(); + // .monotonic is okay because this value shouldn't change until all locks are released, and + // we currently hold a lock. + const id = self.thread_id.load(.monotonic); + + // It's possible for this thread to be the owner (`id == current_id`) and for `owned_count` + // to be 0, if this thread originally wasn't the owner, but became the owner when the + // original owner released all of its locks. In this case, some of the lock count for this + // thread is still in `self.count` rather than `self.owned_count`. + if (id == current_id and self.owned_count > 0) { + self.owned_count -= 1; + if (self.owned_count == 0) { + // .monotonic is okay because: + // * If this succeeds, it means the current thread holds an exclusive lock, so + // concurrent access would be an error. + // * If this fails, we don't care about the value. + _ = self.count.cmpxchgStrong(exclusive, 0, .monotonic, .monotonic); + // .monotonic is okay because another thread that loads `thread_id` should not rely + // on that load to synchronize-with the update to `self.count` above; other + // synchronization should have already been performed. (This type is not meant to + // provide its own synchronization, but rather assert that such synchronization has + // already been provided.) + self.thread_id.store(invalid_thread_id, .monotonic); + } + } else switch (self.count.fetchSub(1, .monotonic)) { + // The .monotonic `fetchSub` above is okay because we don't need to synchronize-with + // other threads (this type is not meant to provide its own synchronization). + 0 => std.debug.panic("called `CriticalSection.end` too many times", .{}), + exclusive => std.debug.panic( + "count should not be `exclusive` if multiple threads hold the lock", + .{}, + ), + else => {}, + } + } +}; + +/// Marks the beginning of a critical section which accesses (and potentially modifies) shared data. +/// Calls to this function can be nested; each must be paired with a call to `end`. +pub fn begin(self: *Self) void { + if (comptime enabled) self.internal_state.lockExclusive(); +} + +/// Marks the beginning of a critical section which performs read-only accesses on shared data. +/// Calls to this function can be nested; each must be paired with a call to `end`. +pub fn beginReadOnly(self: *Self) void { + if (comptime enabled) self.internal_state.lockShared(); +} + +/// Marks the end of a critical section started by `begin` or `beginReadOnly`. +pub fn end(self: *Self) void { + if (comptime enabled) self.internal_state.unlock(); +} + +const bun = @import("bun"); +const enabled = bun.Environment.ci_assert; + +const std = @import("std"); +const Thread = std.Thread; diff --git a/src/collections/safety.zig b/src/safety/alloc_ptr.zig similarity index 100% rename from src/collections/safety.zig rename to src/safety/alloc_ptr.zig diff --git a/src/sourcemap/JSSourceMap.zig b/src/sourcemap/JSSourceMap.zig index 21c5c10b90..3222d56ffd 100644 --- a/src/sourcemap/JSSourceMap.zig +++ b/src/sourcemap/JSSourceMap.zig @@ -6,10 +6,22 @@ sourcemap: *bun.sourcemap.ParsedSourceMap, sources: []bun.String = &.{}, names: []bun.String = &.{}, +/// TODO: when we implement --enable-source-map CLI flag, set this to true. +pub var @"--enable-source-maps" = false; + fn findSourceMap( globalObject: *JSGlobalObject, callFrame: *CallFrame, ) bun.JSError!JSValue { + // Node.js doesn't enable source maps by default. + // In Bun, we do use them for almost all files since we transpile almost all files + // If we enable this by default, we don't have a `payload` object since we don't internally create one. + // This causes Next.js to emit errors like the below on start: + // .next/server/chunks/ssr/[root-of-the-server]__012ba519._.js: Invalid source map. Only conformant source maps can be used to filter stack frames. Cause: TypeError: payload is not an Object. (evaluating '"sections" in payload') + if (!@"--enable-source-maps") { + return .js_undefined; + } + const source_url_value = callFrame.argument(0); if (!source_url_value.isString()) { return .js_undefined; diff --git a/src/sourcemap/sourcemap.zig b/src/sourcemap/sourcemap.zig index a26481b63b..3fffbbcff5 100644 --- a/src/sourcemap/sourcemap.zig +++ b/src/sourcemap/sourcemap.zig @@ -1779,15 +1779,9 @@ pub fn appendSourceMapChunk( start_state.original_line += original_line.value; start_state.original_column += original_column.value; - j.push( - appendMappingToBuffer( - MutableString.initEmpty(allocator), - j.lastByte(), - prev_end_state, - start_state, - ).list.items, - allocator, - ); + var str = MutableString.initEmpty(allocator); + appendMappingToBuffer(&str, j.lastByte(), prev_end_state, start_state); + j.push(str.slice(), allocator); // Then append everything after that without modification. j.pushStatic(source_map); @@ -1812,8 +1806,7 @@ pub fn appendSourceMappingURLRemote( } /// This function is extremely hot. -pub fn appendMappingToBuffer(buffer_: MutableString, last_byte: u8, prev_state: SourceMapState, current_state: SourceMapState) MutableString { - var buffer = buffer_; +pub fn appendMappingToBuffer(buffer: *MutableString, last_byte: u8, prev_state: SourceMapState, current_state: SourceMapState) void { const needs_comma = last_byte != 0 and last_byte != ';' and last_byte != '"'; const vlqs = [_]VLQ{ @@ -1846,8 +1839,6 @@ pub fn appendMappingToBuffer(buffer_: MutableString, last_byte: u8, prev_state: @memcpy(writable[0..item.len], item.slice()); writable = writable[item.len..]; } - - return buffer; } pub const Chunk = struct { @@ -1867,22 +1858,28 @@ pub const Chunk = struct { /// ignore empty chunks should_ignore: bool = true, - pub const empty: Chunk = .{ - .buffer = MutableString.initEmpty(bun.default_allocator), - .mappings_count = 0, - .end_state = .{}, - .final_generated_column = 0, - .should_ignore = true, - }; + pub fn initEmpty() Chunk { + return .{ + .buffer = MutableString.initEmpty(bun.default_allocator), + .mappings_count = 0, + .end_state = .{}, + .final_generated_column = 0, + .should_ignore = true, + }; + } + + pub fn deinit(this: *Chunk) void { + this.buffer.deinit(); + } pub fn printSourceMapContents( chunk: Chunk, source: *const Logger.Source, - mutable: MutableString, + mutable: *MutableString, include_sources_contents: bool, comptime ascii_only: bool, - ) !MutableString { - return printSourceMapContentsAtOffset( + ) !void { + try printSourceMapContentsAtOffset( chunk, source, mutable, @@ -1895,13 +1892,11 @@ pub const Chunk = struct { pub fn printSourceMapContentsAtOffset( chunk: Chunk, source: *const Logger.Source, - mutable: MutableString, + mutable: *MutableString, include_sources_contents: bool, offset: usize, comptime ascii_only: bool, - ) !MutableString { - var output = mutable; - + ) !void { // attempt to pre-allocate var filename_buf: bun.PathBuffer = undefined; @@ -1914,23 +1909,21 @@ pub const Chunk = struct { filename = filename_buf[0 .. filename.len + 1]; } - output.growIfNeeded( + mutable.growIfNeeded( filename.len + 2 + (source.contents.len * @as(usize, @intFromBool(include_sources_contents))) + (chunk.buffer.list.items.len - offset) + 32 + 39 + 29 + 22 + 20, ) catch unreachable; - try output.append("{\n \"version\":3,\n \"sources\": ["); + try mutable.append("{\n \"version\":3,\n \"sources\": ["); - output = try JSPrinter.quoteForJSON(filename, output, ascii_only); + try JSPrinter.quoteForJSON(filename, mutable, ascii_only); if (include_sources_contents) { - try output.append("],\n \"sourcesContent\": ["); - output = try JSPrinter.quoteForJSON(source.contents, output, ascii_only); + try mutable.append("],\n \"sourcesContent\": ["); + try JSPrinter.quoteForJSON(source.contents, mutable, ascii_only); } - try output.append("],\n \"mappings\": "); - output = try JSPrinter.quoteForJSON(chunk.buffer.list.items[offset..], output, ascii_only); - try output.append(", \"names\": []\n}"); - - return output; + try mutable.append("],\n \"mappings\": "); + try JSPrinter.quoteForJSON(chunk.buffer.list.items[offset..], mutable, ascii_only); + try mutable.append(", \"names\": []\n}"); } // TODO: remove the indirection by having generic functions for SourceMapFormat and NewBuilder. Source maps are always VLQ @@ -1959,6 +1952,10 @@ pub const Chunk = struct { return this.ctx.getBuffer(); } + pub inline fn takeBuffer(this: *Format) MutableString { + return this.ctx.takeBuffer(); + } + pub inline fn getCount(this: Format) usize { return this.ctx.getCount(); } @@ -1971,8 +1968,6 @@ pub const Chunk = struct { offset: usize = 0, approximate_input_line_count: usize = 0, - pub const Format = SourceMapFormat(VLQSourceMap); - pub fn init(allocator: std.mem.Allocator, prepend_count: bool) VLQSourceMap { var map = VLQSourceMap{ .data = MutableString.initEmpty(allocator), @@ -1997,7 +1992,7 @@ pub const Chunk = struct { else 0; - this.data = appendMappingToBuffer(this.data, last_byte, prev_state, current_state); + appendMappingToBuffer(&this.data, last_byte, prev_state, current_state); this.count += 1; } @@ -2009,6 +2004,11 @@ pub const Chunk = struct { return this.data; } + pub fn takeBuffer(this: *VLQSourceMap) MutableString { + defer this.data = .initEmpty(this.data.allocator); + return this.data; + } + pub fn getCount(this: VLQSourceMap) usize { return this.count; } @@ -2017,7 +2017,6 @@ pub const Chunk = struct { pub fn NewBuilder(comptime SourceMapFormatType: type) type { return struct { const ThisBuilder = @This(); - input_source_map: ?*SourceMap = null, source_map: SourceMapper, line_offset_tables: LineOffsetTable.List = .{}, prev_state: SourceMapState = SourceMapState{}, @@ -2048,13 +2047,14 @@ pub const Chunk = struct { pub noinline fn generateChunk(b: *ThisBuilder, output: []const u8) Chunk { b.updateGeneratedLineAndColumn(output); + var buffer = b.source_map.getBuffer(); if (b.prepend_count) { - b.source_map.getBuffer().list.items[0..8].* = @as([8]u8, @bitCast(b.source_map.getBuffer().list.items.len)); - b.source_map.getBuffer().list.items[8..16].* = @as([8]u8, @bitCast(b.source_map.getCount())); - b.source_map.getBuffer().list.items[16..24].* = @as([8]u8, @bitCast(b.approximate_input_line_count)); + buffer.list.items[0..8].* = @as([8]u8, @bitCast(buffer.list.items.len)); + buffer.list.items[8..16].* = @as([8]u8, @bitCast(b.source_map.getCount())); + buffer.list.items[16..24].* = @as([8]u8, @bitCast(b.approximate_input_line_count)); } return Chunk{ - .buffer = b.source_map.getBuffer(), + .buffer = b.source_map.takeBuffer(), .mappings_count = b.source_map.getCount(), .end_state = b.prev_state, .final_generated_column = b.generated_column, @@ -2130,17 +2130,7 @@ pub const Chunk = struct { b.last_generated_update = @as(u32, @truncate(output.len)); } - pub fn appendMapping(b: *ThisBuilder, current_state_: SourceMapState) void { - var current_state = current_state_; - // If the input file had a source map, map all the way back to the original - if (b.input_source_map) |input| { - if (input.find(current_state.original_line, current_state.original_column)) |mapping| { - current_state.source_index = mapping.sourceIndex(); - current_state.original_line = mapping.originalLine(); - current_state.original_column = mapping.originalColumn(); - } - } - + pub fn appendMapping(b: *ThisBuilder, current_state: SourceMapState) void { b.appendMappingWithoutRemapping(current_state); } diff --git a/src/sql/postgres/PostgresSQLConnection.zig b/src/sql/postgres/PostgresSQLConnection.zig index 351fbebb51..634c33aed0 100644 --- a/src/sql/postgres/PostgresSQLConnection.zig +++ b/src/sql/postgres/PostgresSQLConnection.zig @@ -1,8 +1,8 @@ const PostgresSQLConnection = @This(); - +const RefCount = bun.ptr.RefCount(@This(), "ref_count", deinit, .{}); socket: Socket, status: Status = Status.connecting, -ref_count: u32 = 1, +ref_count: RefCount = RefCount.init(), write_buffer: bun.OffsetByteList = .{}, read_buffer: bun.OffsetByteList = .{}, @@ -15,7 +15,7 @@ nonpipelinable_requests: u32 = 0, poll_ref: bun.Async.KeepAlive = .{}, globalObject: *jsc.JSGlobalObject, - +vm: *jsc.VirtualMachine, statements: PreparedStatementsMap, prepared_statement_id: u64 = 0, pending_activity_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(0), @@ -66,6 +66,9 @@ max_lifetime_timer: bun.api.Timer.EventLoopTimer = .{ }, auto_flusher: AutoFlusher = .{}, +pub const ref = RefCount.ref; +pub const deref = RefCount.deref; + pub fn onAutoFlush(this: *@This()) bool { if (this.flags.has_backpressure) { debug("onAutoFlush: has backpressure", .{}); @@ -95,7 +98,7 @@ fn registerAutoFlusher(this: *PostgresSQLConnection) void { data_to_send > 0 and // we need data to send this.status == .connected //and we need to be connected ) { - AutoFlusher.registerDeferredMicrotaskWithTypeUnchecked(@This(), this, this.globalObject.bunVM()); + AutoFlusher.registerDeferredMicrotaskWithTypeUnchecked(@This(), this, this.vm); this.auto_flusher.registered = true; } } @@ -103,7 +106,7 @@ fn registerAutoFlusher(this: *PostgresSQLConnection) void { fn unregisterAutoFlusher(this: *PostgresSQLConnection) void { debug("unregisterAutoFlusher registered: {}", .{this.auto_flusher.registered}); if (this.auto_flusher.registered) { - AutoFlusher.unregisterDeferredMicrotaskWithType(@This(), this, this.globalObject.bunVM()); + AutoFlusher.unregisterDeferredMicrotaskWithType(@This(), this, this.vm); this.auto_flusher.registered = false; } } @@ -117,7 +120,7 @@ fn getTimeoutInterval(this: *const PostgresSQLConnection) u32 { } pub fn disableConnectionTimeout(this: *PostgresSQLConnection) void { if (this.timer.state == .ACTIVE) { - this.globalObject.bunVM().timer.remove(&this.timer); + this.vm.timer.remove(&this.timer); } this.timer.state = .CANCELLED; } @@ -126,14 +129,14 @@ pub fn resetConnectionTimeout(this: *PostgresSQLConnection) void { if (this.flags.is_processing_data) return; const interval = this.getTimeoutInterval(); if (this.timer.state == .ACTIVE) { - this.globalObject.bunVM().timer.remove(&this.timer); + this.vm.timer.remove(&this.timer); } if (interval == 0) { return; } this.timer.next = bun.timespec.msFromNow(@intCast(interval)); - this.globalObject.bunVM().timer.insert(&this.timer); + this.vm.timer.insert(&this.timer); } pub fn getQueries(_: *PostgresSQLConnection, thisValue: jsc.JSValue, globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { @@ -192,7 +195,7 @@ fn setupMaxLifetimeTimerIfNecessary(this: *PostgresSQLConnection) void { if (this.max_lifetime_timer.state == .ACTIVE) return; this.max_lifetime_timer.next = bun.timespec.msFromNow(@intCast(this.max_lifetime_interval_ms)); - this.globalObject.bunVM().timer.insert(&this.max_lifetime_timer); + this.vm.timer.insert(&this.max_lifetime_timer); } pub fn onConnectionTimeout(this: *PostgresSQLConnection) bun.api.Timer.EventLoopTimer.Arm { @@ -254,6 +257,7 @@ pub fn setStatus(this: *PostgresSQLConnection, status: Status) void { this.status = status; this.resetConnectionTimeout(); + if (this.vm.isShuttingDown()) return; switch (status) { .connected => { @@ -261,7 +265,7 @@ pub fn setStatus(this: *PostgresSQLConnection, status: Status) void { const js_value = this.js_value; js_value.ensureStillAlive(); this.globalObject.queueMicrotask(on_connect, &[_]JSValue{ JSValue.jsNull(), js_value }); - this.poll_ref.unref(this.globalObject.bunVM()); + this.poll_ref.unref(this.vm); }, else => {}, } @@ -315,7 +319,7 @@ pub fn failWithJSValue(this: *PostgresSQLConnection, value: JSValue) void { defer this.refAndClose(value); const on_close = this.consumeOnCloseCallback(this.globalObject) orelse return; - const loop = this.globalObject.bunVM().eventLoop(); + const loop = this.vm.eventLoop(); loop.enter(); defer loop.exit(); _ = on_close.call( @@ -343,13 +347,21 @@ pub fn fail(this: *PostgresSQLConnection, message: []const u8, err: AnyPostgresE pub fn onClose(this: *PostgresSQLConnection) void { this.unregisterAutoFlusher(); - var vm = this.globalObject.bunVM(); - const loop = vm.eventLoop(); - loop.enter(); - defer loop.exit(); - this.poll_ref.unref(this.globalObject.bunVM()); + if (this.vm.isShuttingDown()) { + defer this.updateHasPendingActivity(); + this.stopTimers(); + if (this.status == .failed) return; - this.fail("Connection closed", error.ConnectionClosed); + this.status = .failed; + this.cleanUpRequests(null); + } else { + const loop = this.vm.eventLoop(); + loop.enter(); + defer loop.exit(); + this.poll_ref.unref(this.vm); + + this.fail("Connection closed", error.ConnectionClosed); + } } fn sendStartupMessage(this: *PostgresSQLConnection) void { @@ -392,7 +404,7 @@ fn startTLS(this: *PostgresSQLConnection, socket: uws.AnySocket) void { pub fn onOpen(this: *PostgresSQLConnection, socket: uws.AnySocket) void { this.socket = socket; - this.poll_ref.ref(this.globalObject.bunVM()); + this.poll_ref.ref(this.vm); this.updateHasPendingActivity(); if (this.tls_status == .message_sent or this.tls_status == .pending) { @@ -460,7 +472,9 @@ pub fn onDrain(this: *PostgresSQLConnection) void { fn drainInternal(this: *PostgresSQLConnection) void { debug("drainInternal", .{}); - const event_loop = this.globalObject.bunVM().eventLoop(); + if (this.vm.isShuttingDown()) return this.close(); + + const event_loop = this.vm.eventLoop(); event_loop.enter(); defer event_loop.exit(); @@ -476,7 +490,7 @@ fn drainInternal(this: *PostgresSQLConnection) void { pub fn onData(this: *PostgresSQLConnection, data: []const u8) void { this.ref(); this.flags.is_processing_data = true; - const vm = this.globalObject.bunVM(); + const vm = this.vm; this.disableConnectionTimeout(); defer { @@ -681,7 +695,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS ptr.* = PostgresSQLConnection{ .globalObject = globalObject, - + .vm = globalObject.bunVM(), .database = database, .user = username, .password = password, @@ -703,16 +717,6 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS }, }; - ptr.updateHasPendingActivity(); - ptr.poll_ref.ref(vm); - const js_value = ptr.toJS(globalObject); - js_value.ensureStillAlive(); - ptr.js_value = js_value; - - js.onconnectSetCached(js_value, globalObject, on_connect); - js.oncloseSetCached(js_value, globalObject, on_close); - bun.analytics.Features.postgres_connections += 1; - { const hostname = hostname_str.toUTF8(bun.default_allocator); defer hostname.deinit(); @@ -747,9 +751,18 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS }, }; } - ptr.resetConnectionTimeout(); } + // only call toJS if connectUnixAnon does not fail immediately + ptr.updateHasPendingActivity(); + ptr.resetConnectionTimeout(); + ptr.poll_ref.ref(vm); + const js_value = ptr.toJS(globalObject); + js_value.ensureStillAlive(); + ptr.js_value = js_value; + js.onconnectSetCached(js_value, globalObject, on_connect); + js.oncloseSetCached(js_value, globalObject, on_close); + bun.analytics.Features.postgres_connections += 1; return js_value; } @@ -764,10 +777,20 @@ fn SocketHandler(comptime ssl: bool) type { return Socket{ .SocketTCP = s }; } pub fn onOpen(this: *PostgresSQLConnection, socket: SocketType) void { + if (this.vm.isShuttingDown()) { + @branchHint(.unlikely); + this.close(); + return; + } this.onOpen(_socket(socket)); } fn onHandshake_(this: *PostgresSQLConnection, _: anytype, success: i32, ssl_error: uws.us_bun_verify_error_t) void { + if (this.vm.isShuttingDown()) { + @branchHint(.unlikely); + this.close(); + return; + } this.onHandshake(success, ssl_error); } @@ -785,39 +808,54 @@ fn SocketHandler(comptime ssl: bool) type { pub fn onConnectError(this: *PostgresSQLConnection, socket: SocketType, _: i32) void { _ = socket; + if (this.vm.isShuttingDown()) { + @branchHint(.unlikely); + this.close(); + return; + } this.onClose(); } pub fn onTimeout(this: *PostgresSQLConnection, socket: SocketType) void { _ = socket; + if (this.vm.isShuttingDown()) { + @branchHint(.unlikely); + this.close(); + return; + } this.onTimeout(); } pub fn onData(this: *PostgresSQLConnection, socket: SocketType, data: []const u8) void { _ = socket; + if (this.vm.isShuttingDown()) { + @branchHint(.unlikely); + this.close(); + return; + } this.onData(data); } pub fn onWritable(this: *PostgresSQLConnection, socket: SocketType) void { _ = socket; + if (this.vm.isShuttingDown()) { + @branchHint(.unlikely); + this.close(); + return; + } this.onDrain(); } }; } -pub fn ref(this: *@This()) void { - bun.assert(this.ref_count > 0); - this.ref_count += 1; -} - pub fn doRef(this: *@This(), _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue { - this.poll_ref.ref(this.globalObject.bunVM()); + this.poll_ref.ref(this.vm); this.updateHasPendingActivity(); return .js_undefined; } pub fn doUnref(this: *@This(), _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue { - this.poll_ref.unref(this.globalObject.bunVM()); + this.poll_ref.unref(this.vm); this.updateHasPendingActivity(); return .js_undefined; } @@ -826,35 +864,29 @@ pub fn doFlush(this: *PostgresSQLConnection, _: *jsc.JSGlobalObject, _: *jsc.Cal return .js_undefined; } -pub fn deref(this: *@This()) void { - const ref_count = this.ref_count; - this.ref_count -= 1; - - if (ref_count == 1) { - this.disconnect(); - this.deinit(); - } +fn close(this: *@This()) void { + this.disconnect(); + this.unregisterAutoFlusher(); + this.write_buffer.deinit(bun.default_allocator); } pub fn doClose(this: *@This(), globalObject: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue { _ = globalObject; - this.disconnect(); - this.unregisterAutoFlusher(); - this.write_buffer.deinit(bun.default_allocator); - + this.close(); return .js_undefined; } pub fn stopTimers(this: *PostgresSQLConnection) void { if (this.timer.state == .ACTIVE) { - this.globalObject.bunVM().timer.remove(&this.timer); + this.vm.timer.remove(&this.timer); } if (this.max_lifetime_timer.state == .ACTIVE) { - this.globalObject.bunVM().timer.remove(&this.max_lifetime_timer); + this.vm.timer.remove(&this.max_lifetime_timer); } } pub fn deinit(this: *@This()) void { + this.disconnect(); this.stopTimers(); var iter = this.statements.valueIterator(); while (iter.next()) |stmt_ptr| { @@ -872,17 +904,7 @@ pub fn deinit(this: *@This()) void { bun.default_allocator.destroy(this); } -fn refAndClose(this: *@This(), js_reason: ?jsc.JSValue) void { - // refAndClose is always called when we wanna to disconnect or when we are closed - - if (!this.socket.isClosed()) { - // event loop need to be alive to close the socket - this.poll_ref.ref(this.globalObject.bunVM()); - // will unref on socket close - this.socket.close(); - } - - // cleanup requests +fn cleanUpRequests(this: *@This(), js_reason: ?jsc.JSValue) void { while (this.current()) |request| { switch (request.status) { // pending we will fail the request and the stmt will be marked as error ConnectionClosed too @@ -890,10 +912,12 @@ fn refAndClose(this: *@This(), js_reason: ?jsc.JSValue) void { const stmt = request.statement orelse continue; stmt.error_response = .{ .postgres_error = AnyPostgresError.ConnectionClosed }; stmt.status = .failed; - if (js_reason) |reason| { - request.onJSError(reason, this.globalObject); - } else { - request.onError(.{ .postgres_error = AnyPostgresError.ConnectionClosed }, this.globalObject); + if (!this.vm.isShuttingDown()) { + if (js_reason) |reason| { + request.onJSError(reason, this.globalObject); + } else { + request.onError(.{ .postgres_error = AnyPostgresError.ConnectionClosed }, this.globalObject); + } } }, // in the middle of running @@ -901,10 +925,12 @@ fn refAndClose(this: *@This(), js_reason: ?jsc.JSValue) void { .running, .partial_response, => { - if (js_reason) |reason| { - request.onJSError(reason, this.globalObject); - } else { - request.onError(.{ .postgres_error = AnyPostgresError.ConnectionClosed }, this.globalObject); + if (!this.vm.isShuttingDown()) { + if (js_reason) |reason| { + request.onJSError(reason, this.globalObject); + } else { + request.onError(.{ .postgres_error = AnyPostgresError.ConnectionClosed }, this.globalObject); + } } }, // just ignore success and fail cases @@ -914,6 +940,19 @@ fn refAndClose(this: *@This(), js_reason: ?jsc.JSValue) void { this.requests.discard(1); } } +fn refAndClose(this: *@This(), js_reason: ?jsc.JSValue) void { + // refAndClose is always called when we wanna to disconnect or when we are closed + + if (!this.socket.isClosed()) { + // event loop need to be alive to close the socket + this.poll_ref.ref(this.vm); + // will unref on socket close + this.socket.close(); + } + + // cleanup requests + this.cleanUpRequests(js_reason); +} pub fn disconnect(this: *@This()) void { this.stopTimers(); @@ -928,6 +967,7 @@ fn current(this: *PostgresSQLConnection) ?*PostgresSQLQuery { if (this.requests.readableLength() == 0) { return null; } + return this.requests.peekItem(0); } @@ -1022,10 +1062,42 @@ pub fn bufferedReader(this: *PostgresSQLConnection) protocol.NewReader(Reader) { }; } +fn cleanupSuccessQuery(this: *PostgresSQLConnection, item: *PostgresSQLQuery) void { + if (item.flags.simple) { + this.nonpipelinable_requests -= 1; + } else if (item.flags.pipelined) { + this.pipelined_requests -= 1; + } else if (this.flags.waiting_to_prepare) { + this.flags.waiting_to_prepare = false; + } +} fn advance(this: *PostgresSQLConnection) void { var offset: usize = 0; debug("advance", .{}); + defer { + while (this.requests.readableLength() > 0) { + const result = this.requests.peekItem(0); + // An item may be in the success or failed state and still be inside the queue (see deinit later comments) + // so we do the cleanup her + switch (result.status) { + .success => { + this.cleanupSuccessQuery(result); + result.deref(); + this.requests.discard(1); + continue; + }, + .fail => { + result.deref(); + this.requests.discard(1); + continue; + }, + else => break, // trully current item + } + } + } while (this.requests.readableLength() > offset and !this.flags.has_backpressure) { + if (this.vm.isShuttingDown()) return this.close(); + var req: *PostgresSQLQuery = this.requests.peekItem(offset); switch (req.status) { .pending => { @@ -1084,8 +1156,18 @@ fn advance(this: *PostgresSQLConnection) void { continue; }, .prepared => { - const thisValue = req.thisValue.get(); - bun.assert(thisValue != .zero); + const thisValue = req.thisValue.tryGet() orelse { + bun.assertf(false, "query value was freed earlier than expected", .{}); + if (offset == 0) { + req.deref(); + this.requests.discard(1); + } else { + // deinit later + req.status = .fail; + offset += 1; + } + continue; + }; const binding_value = PostgresSQLQuery.js.bindingGetCached(thisValue) orelse .zero; const columns_value = PostgresSQLQuery.js.columnsGetCached(thisValue) orelse .zero; req.flags.binary = stmt.fields.len > 0; @@ -1129,8 +1211,18 @@ fn advance(this: *PostgresSQLConnection) void { const has_params = stmt.signature.fields.len > 0; // If it does not have params, we can write and execute immediately in one go if (!has_params) { - const thisValue = req.thisValue.get(); - bun.assert(thisValue != .zero); + const thisValue = req.thisValue.tryGet() orelse { + bun.assertf(false, "query value was freed earlier than expected", .{}); + if (offset == 0) { + req.deref(); + this.requests.discard(1); + } else { + // deinit later + req.status = .fail; + offset += 1; + } + continue; + }; // prepareAndQueryWithSignature will write + bind + execute, it will change to running after binding is complete const binding_value = PostgresSQLQuery.js.bindingGetCached(thisValue) orelse .zero; debug("prepareAndQueryWithSignature", .{}); @@ -1201,13 +1293,7 @@ fn advance(this: *PostgresSQLConnection) void { return; }, .success => { - if (req.flags.simple) { - this.nonpipelinable_requests -= 1; - } else if (req.flags.pipelined) { - this.pipelined_requests -= 1; - } else if (this.flags.waiting_to_prepare) { - this.flags.waiting_to_prepare = false; - } + this.cleanupSuccessQuery(req); if (offset > 0) { // deinit later req.status = .fail; @@ -1242,6 +1328,7 @@ pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.enum_litera switch (comptime MessageType) { .DataRow => { const request = this.current() orelse return error.ExpectedRequest; + var statement = request.statement orelse return error.ExpectedStatement; var structure: JSValue = .js_undefined; var cached_structure: ?PostgresCachedStructure = null; @@ -1297,8 +1384,10 @@ pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.enum_litera DataCell.Putter.put, ); } - const thisValue = request.thisValue.get(); - bun.assert(thisValue != .zero); + const thisValue = request.thisValue.tryGet() orelse return { + bun.assertf(false, "query value was freed earlier than expected", .{}); + return error.ExpectedRequest; + }; const pending_value = PostgresSQLQuery.js.pendingValueGetCached(thisValue) orelse .zero; pending_value.ensureStillAlive(); const result = putter.toJS(this.globalObject, pending_value, structure, statement.fields_flags, request.flags.result_mode, cached_structure); @@ -1682,9 +1771,9 @@ pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.enum_litera pub fn updateRef(this: *PostgresSQLConnection) void { this.updateHasPendingActivity(); if (this.pending_activity_count.raw > 0) { - this.poll_ref.ref(this.globalObject.bunVM()); + this.poll_ref.ref(this.vm); } else { - this.poll_ref.unref(this.globalObject.bunVM()); + this.poll_ref.unref(this.vm); } } diff --git a/src/sql/postgres/PostgresSQLQuery.zig b/src/sql/postgres/PostgresSQLQuery.zig index 79b3f67311..7d51065e41 100644 --- a/src/sql/postgres/PostgresSQLQuery.zig +++ b/src/sql/postgres/PostgresSQLQuery.zig @@ -1,5 +1,5 @@ const PostgresSQLQuery = @This(); - +const RefCount = bun.ptr.ThreadSafeRefCount(@This(), "ref_count", deinit, .{}); statement: ?*PostgresSQLStatement = null, query: bun.String = bun.String.empty, cursor_name: bun.String = bun.String.empty, @@ -8,7 +8,7 @@ thisValue: JSRef = JSRef.empty(), status: Status = Status.pending, -ref_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(1), +ref_count: RefCount = RefCount.init(), flags: packed struct(u8) { is_done: bool = false, @@ -20,11 +20,11 @@ flags: packed struct(u8) { _padding: u1 = 0, } = .{}, +pub const ref = RefCount.ref; +pub const deref = RefCount.deref; + pub fn getTarget(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, clean_target: bool) jsc.JSValue { - const thisValue = this.thisValue.get(); - if (thisValue == .zero) { - return .zero; - } + const thisValue = this.thisValue.tryGet() orelse return .zero; const target = js.targetGetCached(thisValue) orelse return .zero; if (clean_target) { js.targetSetCached(thisValue, globalObject, .zero); @@ -52,7 +52,7 @@ pub const Status = enum(u8) { }; pub fn hasPendingActivity(this: *@This()) bool { - return this.ref_count.load(.monotonic) > 1; + return this.ref_count.getCount() > 1; } pub fn deinit(this: *@This()) void { @@ -75,24 +75,14 @@ pub fn finalize(this: *@This()) void { this.deref(); } -pub fn deref(this: *@This()) void { - const ref_count = this.ref_count.fetchSub(1, .monotonic); - - if (ref_count == 1) { - this.deinit(); - } -} - -pub fn ref(this: *@This()) void { - bun.assert(this.ref_count.fetchAdd(1, .monotonic) > 0); -} - pub fn onWriteFail( this: *@This(), err: AnyPostgresError, globalObject: *jsc.JSGlobalObject, queries_array: JSValue, ) void { + this.ref(); + defer this.deref(); this.status = .fail; const thisValue = this.thisValue.get(); defer this.thisValue.deinit(); @@ -111,10 +101,9 @@ pub fn onWriteFail( }); } pub fn onJSError(this: *@This(), err: jsc.JSValue, globalObject: *jsc.JSGlobalObject) void { - this.status = .fail; this.ref(); defer this.deref(); - + this.status = .fail; const thisValue = this.thisValue.get(); defer this.thisValue.deinit(); const targetValue = this.getTarget(globalObject, true); @@ -268,7 +257,8 @@ pub fn doDone(this: *@This(), globalObject: *jsc.JSGlobalObject, _: *jsc.CallFra } pub fn setPendingValue(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue { const result = callframe.argument(0); - js.pendingValueSetCached(this.thisValue.get(), globalObject, result); + const thisValue = this.thisValue.tryGet() orelse return .js_undefined; + js.pendingValueSetCached(thisValue, globalObject, result); return .js_undefined; } pub fn setMode(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue { @@ -303,13 +293,30 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra var query_str = this.query.toUTF8(bun.default_allocator); defer query_str.deinit(); var writer = connection.writer(); - + // We need a strong reference to the query so that it doesn't get GC'd + this.ref(); if (this.flags.simple) { debug("executeQuery", .{}); + const stmt = bun.default_allocator.create(PostgresSQLStatement) catch { + this.deref(); + return globalObject.throwOutOfMemory(); + }; + // Query is simple and it's the only owner of the statement + stmt.* = .{ + .signature = Signature.empty(), + .status = .parsing, + }; + this.statement = stmt; + const can_execute = !connection.hasQueryRunning(); if (can_execute) { PostgresRequest.executeQuery(query_str.slice(), PostgresSQLConnection.Writer, writer) catch |err| { + // fail to run do cleanup + this.statement = null; + bun.default_allocator.destroy(stmt); + this.deref(); + if (!globalObject.hasException()) return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to execute query", err)); return error.JSError; @@ -320,21 +327,16 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra } else { this.status = .pending; } - const stmt = bun.default_allocator.create(PostgresSQLStatement) catch { + connection.requests.writeItem(this) catch { + // fail to run do cleanup + this.statement = null; + bun.default_allocator.destroy(stmt); + this.deref(); + return globalObject.throwOutOfMemory(); }; - // Query is simple and it's the only owner of the statement - stmt.* = .{ - .signature = Signature.empty(), - .ref_count = 1, - .status = .parsing, - }; - this.statement = stmt; - // We need a strong reference to the query so that it doesn't get GC'd - connection.requests.writeItem(this) catch return globalObject.throwOutOfMemory(); - this.ref(); - this.thisValue.upgrade(globalObject); + this.thisValue.upgrade(globalObject); js.targetSetCached(this_value, globalObject, query); if (this.status == .running) { connection.flushDataAndResetTimeout(); @@ -347,6 +349,7 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra const columns_value: JSValue = js.columnsGetCached(this_value) orelse .js_undefined; var signature = Signature.generate(globalObject, query_str.slice(), binding_value, columns_value, connection.prepared_statement_id, connection.flags.use_unnamed_prepared_statements) catch |err| { + this.deref(); if (!globalObject.hasException()) return globalObject.throwError(err, "failed to generate signature"); return error.JSError; @@ -363,12 +366,16 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra }; connection_entry_value = entry.value_ptr; if (entry.found_existing) { - this.statement = connection_entry_value.?.*; - this.statement.?.ref(); + const stmt = connection_entry_value.?.*; + this.statement = stmt; + stmt.ref(); signature.deinit(); - switch (this.statement.?.status) { + switch (stmt.status) { .failed => { + this.statement = null; + stmt.deref(); + this.deref(); // If the statement failed, we need to throw the error return globalObject.throwValue(this.statement.?.error_response.?.toJS(globalObject)); }, @@ -379,6 +386,11 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra // bindAndExecute will bind + execute, it will change to running after binding is complete PostgresRequest.bindAndExecute(globalObject, this.statement.?, binding_value, columns_value, PostgresSQLConnection.Writer, writer) catch |err| { + // fail to run do cleanup + this.statement = null; + stmt.deref(); + this.deref(); + if (!globalObject.hasException()) return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to bind and execute query", err)); return error.JSError; @@ -406,6 +418,11 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra // prepareAndQueryWithSignature will write + bind + execute, it will change to running after binding is complete PostgresRequest.prepareAndQueryWithSignature(globalObject, query_str.slice(), binding_value, PostgresSQLConnection.Writer, writer, &signature) catch |err| { signature.deinit(); + if (this.statement) |stmt| { + this.statement = null; + stmt.deref(); + } + this.deref(); if (!globalObject.hasException()) return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to prepare and query", err)); return error.JSError; @@ -419,6 +436,11 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra PostgresRequest.writeQuery(query_str.slice(), signature.prepared_statement_name, signature.fields, PostgresSQLConnection.Writer, writer) catch |err| { signature.deinit(); + if (this.statement) |stmt| { + this.statement = null; + stmt.deref(); + } + this.deref(); if (!globalObject.hasException()) return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to write query", err)); return error.JSError; @@ -436,24 +458,31 @@ pub fn doRun(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callfra } { const stmt = bun.default_allocator.create(PostgresSQLStatement) catch { + this.deref(); return globalObject.throwOutOfMemory(); }; // we only have connection_entry_value if we are using named prepared statements if (connection_entry_value) |entry_value| { connection.prepared_statement_id += 1; - stmt.* = .{ .signature = signature, .ref_count = 2, .status = if (can_execute) .parsing else .pending }; + stmt.* = .{ + .signature = signature, + .ref_count = .initExactRefs(2), + .status = if (can_execute) .parsing else .pending, + }; this.statement = stmt; entry_value.* = stmt; } else { - stmt.* = .{ .signature = signature, .ref_count = 1, .status = if (can_execute) .parsing else .pending }; + stmt.* = .{ + .signature = signature, + .status = if (can_execute) .parsing else .pending, + }; this.statement = stmt; } } } - // We need a strong reference to the query so that it doesn't get GC'd + connection.requests.writeItem(this) catch return globalObject.throwOutOfMemory(); - this.ref(); this.thisValue.upgrade(globalObject); js.targetSetCached(this_value, globalObject, query); diff --git a/src/sql/postgres/PostgresSQLStatement.zig b/src/sql/postgres/PostgresSQLStatement.zig index c238a19676..644ea5800b 100644 --- a/src/sql/postgres/PostgresSQLStatement.zig +++ b/src/sql/postgres/PostgresSQLStatement.zig @@ -1,7 +1,7 @@ const PostgresSQLStatement = @This(); - +const RefCount = bun.ptr.RefCount(@This(), "ref_count", deinit, .{}); cached_structure: PostgresCachedStructure = .{}, -ref_count: u32 = 1, +ref_count: RefCount = RefCount.init(), fields: []protocol.FieldDescription = &[_]protocol.FieldDescription{}, parameters: []const int4 = &[_]int4{}, signature: Signature, @@ -9,6 +9,8 @@ status: Status = Status.pending, error_response: ?Error = null, needs_duplicate_check: bool = true, fields_flags: DataCell.Flags = .{}, +pub const ref = RefCount.ref; +pub const deref = RefCount.deref; pub const Error = union(enum) { protocol: protocol.ErrorResponse, @@ -38,19 +40,6 @@ pub const Status = enum { return this == .parsing; } }; -pub fn ref(this: *@This()) void { - bun.assert(this.ref_count > 0); - this.ref_count += 1; -} - -pub fn deref(this: *@This()) void { - const ref_count = this.ref_count; - this.ref_count -= 1; - - if (ref_count == 1) { - this.deinit(); - } -} pub fn checkForDuplicateFields(this: *PostgresSQLStatement) void { if (!this.needs_duplicate_check) return; @@ -100,7 +89,7 @@ pub fn checkForDuplicateFields(this: *PostgresSQLStatement) void { pub fn deinit(this: *PostgresSQLStatement) void { debug("PostgresSQLStatement deinit", .{}); - bun.assert(this.ref_count == 0); + this.ref_count.assertNoRefs(); for (this.fields) |*field| { field.deinit(); diff --git a/src/sql/postgres/protocol/NewReader.zig b/src/sql/postgres/protocol/NewReader.zig index 87a1e1f1cb..5832f65953 100644 --- a/src/sql/postgres/protocol/NewReader.zig +++ b/src/sql/postgres/protocol/NewReader.zig @@ -57,10 +57,14 @@ pub fn NewReaderWrap( pub fn int(this: @This(), comptime Int: type) !Int { var data = try this.read(@sizeOf((Int))); defer data.deinit(); - if (comptime Int == u8) { - return @as(Int, data.slice()[0]); + const slice = data.slice(); + if (slice.len < @sizeOf(Int)) { + return error.ShortRead; } - return @byteSwap(@as(Int, @bitCast(data.slice()[0..@sizeOf(Int)].*))); + if (comptime Int == u8) { + return @as(Int, slice[0]); + } + return @byteSwap(@as(Int, @bitCast(slice[0..@sizeOf(Int)].*))); } pub fn peekInt(this: @This(), comptime Int: type) ?Int { diff --git a/src/string.zig b/src/string.zig index fddb9b320a..37b15dcce5 100644 --- a/src/string.zig +++ b/src/string.zig @@ -757,20 +757,13 @@ pub const String = extern struct { pub fn toThreadSafeSlice(this: *const String, allocator: std.mem.Allocator) SliceWithUnderlyingString { if (this.tag == .WTFStringImpl) { if (!this.value.WTFStringImpl.isThreadSafe()) { - const slice = this.value.WTFStringImpl.toUTF8WithoutRef(allocator); + const slice = this.value.WTFStringImpl.toUTF8(allocator); - if (slice.allocator.isNull()) { - // this was a WTF-allocated string - // We're going to need to clone it across the threads - // so let's just do that now instead of creating another copy. - return .{ - .utf8 = ZigString.Slice.init(allocator, allocator.dupe(u8, slice.slice()) catch bun.outOfMemory()), - }; - } + bun.debugAssert(!slice.allocator.isNull()); if (comptime bun.Environment.allow_assert) { - bun.assert(!isWTFAllocator(slice.allocator.get().?)); // toUTF8WithoutRef() should never return a WTF allocator - bun.assert(slice.allocator.get().?.vtable == allocator.vtable); // assert that the allocator is the same + // bun.assert(!isWTFAllocator(slice.allocator.get().?)); // toUTF8WithoutRef() should never return a WTF allocator + // bun.assert(slice.allocator.get().?.vtable == allocator.vtable); // assert that the allocator is the same } // We've already cloned the string, so let's just return the slice. diff --git a/src/string/MutableString.zig b/src/string/MutableString.zig index 643e51ca39..42e22b2b3d 100644 --- a/src/string/MutableString.zig +++ b/src/string/MutableString.zig @@ -240,7 +240,7 @@ pub inline fn lenI(self: *MutableString) i32 { return @as(i32, @intCast(self.list.items.len)); } -pub fn toOwnedSlice(self: *MutableString) string { +pub fn toOwnedSlice(self: *MutableString) []u8 { return self.list.toOwnedSlice(self.allocator) catch bun.outOfMemory(); // TODO } diff --git a/src/string/StringJoiner.zig b/src/string/StringJoiner.zig index c18a7a54e0..bb2083d053 100644 --- a/src/string/StringJoiner.zig +++ b/src/string/StringJoiner.zig @@ -104,6 +104,20 @@ pub fn done(this: *StringJoiner, allocator: Allocator) ![]u8 { return slice; } +pub fn deinit(this: *StringJoiner) void { + var current: ?*Node = this.head orelse { + assert(this.tail == null); + assert(this.len == 0); + return; + }; + + while (current) |node| { + const prev = node; + current = node.next; + prev.deinit(this.allocator); + } +} + /// Same as `.done`, but appends extra slice `end` pub fn doneWithEnd(this: *StringJoiner, allocator: Allocator, end: []const u8) ![]u8 { var current: ?*Node = this.head orelse { diff --git a/src/sys.zig b/src/sys.zig index 25202a9a57..0e71780d53 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -299,332 +299,7 @@ pub const Tag = enum(u8) { pub var strings = std.EnumMap(Tag, jsc.C.JSStringRef).initFull(null); }; -pub const Error = struct { - const retry_errno = if (Environment.isLinux) - @as(Int, @intCast(@intFromEnum(E.AGAIN))) - else if (Environment.isMac) - @as(Int, @intCast(@intFromEnum(E.AGAIN))) - else - @as(Int, @intCast(@intFromEnum(E.INTR))); - - const todo_errno = std.math.maxInt(Int) - 1; - - pub const Int = u16; - - /// TODO: convert to function - pub const oom = fromCode(E.NOMEM, .read); - - errno: Int = todo_errno, - fd: bun.FileDescriptor = bun.invalid_fd, - from_libuv: if (Environment.isWindows) bool else void = if (Environment.isWindows) false else undefined, - path: []const u8 = "", - syscall: sys.Tag = sys.Tag.TODO, - dest: []const u8 = "", - - pub fn clone(this: *const Error, allocator: std.mem.Allocator) Error { - var copy = this.*; - copy.path = allocator.dupe(u8, copy.path) catch bun.outOfMemory(); - copy.dest = allocator.dupe(u8, copy.dest) catch bun.outOfMemory(); - return copy; - } - - pub fn fromCode(errno: E, syscall_tag: sys.Tag) Error { - return .{ - .errno = @as(Int, @intCast(@intFromEnum(errno))), - .syscall = syscall_tag, - }; - } - - pub fn fromCodeInt(errno: anytype, syscall_tag: sys.Tag) Error { - return .{ - .errno = @as(Int, @intCast(if (Environment.isWindows) @abs(errno) else errno)), - .syscall = syscall_tag, - }; - } - - pub fn format(self: Error, comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void { - // We want to reuse the code from SystemError for formatting. - // But, we do not want to call String.createUTF8 on the path/dest strings - // because we're intending to pass them to writer.print() - // which will convert them back into UTF*. - var that = self.withoutPath().toShellSystemError(); - bun.debugAssert(that.path.tag != .WTFStringImpl); - bun.debugAssert(that.dest.tag != .WTFStringImpl); - that.path = bun.String.borrowUTF8(self.path); - that.dest = bun.String.borrowUTF8(self.dest); - bun.debugAssert(that.path.tag != .WTFStringImpl); - bun.debugAssert(that.dest.tag != .WTFStringImpl); - - return that.format(fmt, opts, writer); - } - - pub inline fn getErrno(this: Error) E { - return @as(E, @enumFromInt(this.errno)); - } - - pub inline fn isRetry(this: *const Error) bool { - return this.getErrno() == .AGAIN; - } - - pub const retry = Error{ - .errno = retry_errno, - .syscall = .read, - }; - - pub inline fn withFd(this: Error, fd: anytype) Error { - if (Environment.allow_assert) bun.assert(fd != bun.invalid_fd); - return Error{ - .errno = this.errno, - .syscall = this.syscall, - .fd = fd, - }; - } - - pub inline fn withPath(this: Error, path: anytype) Error { - if (std.meta.Child(@TypeOf(path)) == u16) { - @compileError("Do not pass WString path to withPath, it needs the path encoded as utf8"); - } - return Error{ - .errno = this.errno, - .syscall = this.syscall, - .path = bun.span(path), - }; - } - - pub inline fn withPathAndSyscall(this: Error, path: anytype, syscall_: sys.Tag) Error { - if (std.meta.Child(@TypeOf(path)) == u16) { - @compileError("Do not pass WString path to withPath, it needs the path encoded as utf8"); - } - return Error{ - .errno = this.errno, - .syscall = syscall_, - .path = bun.span(path), - }; - } - - pub fn deinit(this: *Error) void { - this.deinitWithAllocator(bun.default_allocator); - } - - /// Only call this after it's been .clone()'d - pub fn deinitWithAllocator(this: *Error, allocator: std.mem.Allocator) void { - if (this.path.len > 0) { - allocator.free(this.path); - this.path = ""; - } - if (this.dest.len > 0) { - allocator.free(this.dest); - this.dest = ""; - } - } - - pub inline fn withPathDest(this: Error, path: anytype, dest: anytype) Error { - if (std.meta.Child(@TypeOf(path)) == u16) { - @compileError("Do not pass WString path to withPathDest, it needs the path encoded as utf8 (path)"); - } - if (std.meta.Child(@TypeOf(dest)) == u16) { - @compileError("Do not pass WString path to withPathDest, it needs the path encoded as utf8 (dest)"); - } - return Error{ - .errno = this.errno, - .syscall = this.syscall, - .path = bun.span(path), - .dest = bun.span(dest), - }; - } - - pub inline fn withPathLike(this: Error, pathlike: anytype) Error { - return switch (pathlike) { - .fd => |fd| this.withFd(fd), - .path => |path| this.withPath(path.slice()), - }; - } - - /// When the memory of the path/dest buffer is unsafe to use, call this function to clone the error without the path/dest. - pub fn withoutPath(this: *const Error) Error { - var copy = this.*; - copy.path = ""; - copy.dest = ""; - return copy; - } - - pub fn name(this: *const Error) []const u8 { - if (comptime Environment.isWindows) { - const system_errno = brk: { - // setRuntimeSafety(false) because we use tagName function, which will be null on invalid enum value. - @setRuntimeSafety(false); - if (this.from_libuv) { - break :brk @as(SystemErrno, @enumFromInt(@intFromEnum(bun.windows.libuv.translateUVErrorToE(this.errno)))); - } - - break :brk @as(SystemErrno, @enumFromInt(this.errno)); - }; - if (bun.tagName(SystemErrno, system_errno)) |errname| { - return errname; - } - } else if (this.errno > 0 and this.errno < SystemErrno.max) { - const system_errno = @as(SystemErrno, @enumFromInt(this.errno)); - if (bun.tagName(SystemErrno, system_errno)) |errname| { - return errname; - } - } - - return "UNKNOWN"; - } - - pub fn toZigErr(this: Error) anyerror { - return bun.errnoToZigErr(this.errno); - } - - /// 1. Convert libuv errno values into libc ones. - /// 2. Get the tag name as a string for printing. - pub fn getErrorCodeTagName(err: *const Error) ?struct { [:0]const u8, SystemErrno } { - if (!Environment.isWindows) { - if (err.errno > 0 and err.errno < SystemErrno.max) { - const system_errno = @as(SystemErrno, @enumFromInt(err.errno)); - return .{ @tagName(system_errno), system_errno }; - } - } else { - const system_errno: SystemErrno = brk: { - // setRuntimeSafety(false) because we use tagName function, which will be null on invalid enum value. - @setRuntimeSafety(false); - if (err.from_libuv) { - break :brk @enumFromInt(@intFromEnum(bun.windows.libuv.translateUVErrorToE(@as(c_int, err.errno) * -1))); - } - - break :brk @enumFromInt(err.errno); - }; - if (bun.tagName(SystemErrno, system_errno)) |errname| { - return .{ errname, system_errno }; - } - } - return null; - } - - pub fn msg(this: Error) ?[]const u8 { - if (this.getErrorCodeTagName()) |resolved_errno| { - const code, const system_errno = resolved_errno; - if (coreutils_error_map.get(system_errno)) |label| { - return label; - } - return code; - } - return null; - } - - /// Simpler formatting which does not allocate a message - pub fn toShellSystemError(this: Error) SystemError { - @setEvalBranchQuota(1_000_000); - var err = SystemError{ - .errno = @as(c_int, this.errno) * -1, - .syscall = bun.String.static(@tagName(this.syscall)), - .message = .empty, - }; - - // errno label - if (this.getErrorCodeTagName()) |resolved_errno| { - const code, const system_errno = resolved_errno; - err.code = bun.String.static(code); - if (coreutils_error_map.get(system_errno)) |label| { - err.message = bun.String.static(label); - } - } - - if (this.path.len > 0) { - err.path = bun.String.cloneUTF8(this.path); - } - - if (this.dest.len > 0) { - err.dest = bun.String.cloneUTF8(this.dest); - } - - if (this.fd.unwrapValid()) |valid| { - // When the FD is a windows handle, there is no sane way to report this. - if (!Environment.isWindows or valid.kind == .uv) { - err.fd = valid.uv(); - } - } - - return err; - } - - /// More complex formatting to precisely match the printing that Node.js emits. - /// Use this whenever the error will be sent to JavaScript instead of the shell variant above. - pub fn toSystemError(this: Error) SystemError { - var err = SystemError{ - .errno = -%@as(c_int, this.errno), - .syscall = bun.String.static(@tagName(this.syscall)), - .message = .empty, - }; - - // errno label - var maybe_code: ?[:0]const u8 = null; - var label: ?[]const u8 = null; - if (this.getErrorCodeTagName()) |resolved_errno| { - maybe_code, const system_errno = resolved_errno; - err.code = bun.String.static(maybe_code.?); - label = libuv_error_map.get(system_errno); - } - - // format taken from Node.js 'exceptions.cc' - // search keyword: `Local UVException(Isolate* isolate,` - var message_buf: [4096]u8 = @splat(0); - const message = message: { - var stream = std.io.fixedBufferStream(&message_buf); - const writer = stream.writer(); - brk: { - if (maybe_code) |code| { - writer.writeAll(code) catch break :brk; - writer.writeAll(": ") catch break :brk; - } - writer.writeAll(label orelse "Unknown Error") catch break :brk; - writer.writeAll(", ") catch break :brk; - writer.writeAll(@tagName(this.syscall)) catch break :brk; - if (this.path.len > 0) { - writer.writeAll(" '") catch break :brk; - writer.writeAll(this.path) catch break :brk; - writer.writeAll("'") catch break :brk; - - if (this.dest.len > 0) { - writer.writeAll(" -> '") catch break :brk; - writer.writeAll(this.dest) catch break :brk; - writer.writeAll("'") catch break :brk; - } - } - } - break :message stream.getWritten(); - }; - err.message = bun.String.cloneUTF8(message); - - if (this.path.len > 0) { - err.path = bun.String.cloneUTF8(this.path); - } - - if (this.dest.len > 0) { - err.dest = bun.String.cloneUTF8(this.dest); - } - - if (this.fd.unwrapValid()) |valid| { - // When the FD is a windows handle, there is no sane way to report this. - if (!Environment.isWindows or valid.kind == .uv) { - err.fd = valid.uv(); - } - } - - return err; - } - - pub inline fn todo() Error { - if (Environment.isDebug) { - @panic("Error.todo() was called"); - } - return Error{ .errno = todo_errno, .syscall = .TODO }; - } - - pub fn toJS(this: Error, ptr: *jsc.JSGlobalObject) jsc.JSValue { - return this.toSystemError().toErrorInstance(ptr); - } -}; +pub const Error = @import("./sys/Error.zig"); pub fn Maybe(comptime ReturnTypeT: type) type { return bun.api.node.Maybe(ReturnTypeT, Error); @@ -1621,7 +1296,7 @@ pub fn openatWindowsT(comptime T: type, dir: bun.FileDescriptor, path: []const T return openatWindowsTMaybeNormalize(T, dir, path, flags, perm, true); } -fn openatWindowsTMaybeNormalize(comptime T: type, dir: bun.FileDescriptor, path: []const T, flags: i32, perm: bun.Mode, comptime normalize: bool) Maybe(bun.FileDescriptor) { +pub fn openatWindowsTMaybeNormalize(comptime T: type, dir: bun.FileDescriptor, path: []const T, flags: i32, perm: bun.Mode, comptime normalize: bool) Maybe(bun.FileDescriptor) { if (flags & O.DIRECTORY != 0) { const windows_options: WindowsOpenDirOptions = .{ .iterable = flags & O.PATH == 0, @@ -4010,803 +3685,11 @@ pub fn isPollable(mode: mode_t) bool { return posix.S.ISFIFO(mode) or posix.S.ISSOCK(mode); } -/// TODO: make these all methods on `bun.FD`, and define them as methods `bun.FD` -pub const File = struct { - // "handle" matches std.fs.File - handle: bun.FileDescriptor, - - pub fn openat(dir: bun.FileDescriptor, path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { - return switch (This.openat(dir, path, flags, mode)) { - .result => |fd| .{ .result = .{ .handle = fd } }, - .err => |err| .{ .err = err }, - }; - } - - pub fn open(path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { - return File.openat(bun.FD.cwd(), path, flags, mode); - } - - pub fn makeOpen(path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { - return File.makeOpenat(bun.FD.cwd(), path, flags, mode); - } - - pub fn makeOpenat(other: bun.FD, path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { - const fd = switch (This.openat(other, path, flags, mode)) { - .result => |fd| fd, - .err => |err| fd: { - if (std.fs.path.dirname(path)) |dir_path| { - bun.makePath(other.stdDir(), dir_path) catch {}; - break :fd switch (This.openat(other, path, flags, mode)) { - .result => |fd| fd, - .err => |err2| return .{ .err = err2 }, - }; - } - - return .{ .err = err }; - }, - }; - - return .{ .result = .{ .handle = fd } }; - } - - pub fn openatOSPath(other: bun.FD, path: bun.OSPathSliceZ, flags: i32, mode: bun.Mode) Maybe(File) { - return switch (This.openatOSPath(other, path, flags, mode)) { - .result => |fd| .{ .result = .{ .handle = fd } }, - .err => |err| .{ .err = err }, - }; - } - - pub fn from(other: anytype) File { - const T = @TypeOf(other); - - if (T == File) { - return other; - } - - if (T == std.posix.fd_t) { - return .{ .handle = .fromNative(other) }; - } - - if (T == bun.FileDescriptor) { - return .{ .handle = other }; - } - - if (T == std.fs.File) { - return .{ .handle = .fromStdFile(other) }; - } - - if (T == std.fs.Dir) { - return File{ .handle = .fromStdDir(other) }; - } - - if (comptime Environment.isLinux) { - if (T == u64) { - return File{ .handle = .fromNative(@intCast(other)) }; - } - } - - @compileError("Unsupported type " ++ bun.meta.typeName(T)); - } - - pub fn write(self: File, buf: []const u8) Maybe(usize) { - return This.write(self.handle, buf); - } - - pub fn read(self: File, buf: []u8) Maybe(usize) { - return This.read(self.handle, buf); - } - - pub fn readAll(self: File, buf: []u8) Maybe(usize) { - return This.readAll(self.handle, buf); - } - - pub fn writeAll(self: File, buf: []const u8) Maybe(void) { - var remain = buf; - while (remain.len > 0) { - const rc = This.write(self.handle, remain); - switch (rc) { - .err => |err| return .{ .err = err }, - .result => |amt| { - if (amt == 0) { - return .success; - } - remain = remain[amt..]; - }, - } - } - - return .success; - } - - pub fn writeFile( - relative_dir_or_cwd: anytype, - path: bun.OSPathSliceZ, - data: []const u8, - ) Maybe(void) { - const file = switch (File.openatOSPath(relative_dir_or_cwd, path, bun.O.WRONLY | bun.O.CREAT | bun.O.TRUNC, 0o664)) { - .err => |err| return .{ .err = err }, - .result => |fd| fd, - }; - defer file.close(); - switch (file.writeAll(data)) { - .err => |err| return .{ .err = err }, - .result => {}, - } - return .success; - } - - pub const ReadError = anyerror; - - pub fn closeAndMoveTo(this: File, src: [:0]const u8, dest: [:0]const u8) !void { - // On POSIX, close the file after moving it. - defer if (Environment.isPosix) this.close(); - // On Windows, close the file before moving it. - if (Environment.isWindows) this.close(); - const cwd = bun.FD.cwd(); - try bun.sys.moveFileZWithHandle(this.handle, cwd, src, cwd, dest); - } - - fn stdIoRead(this: File, buf: []u8) ReadError!usize { - return try this.read(buf).unwrap(); - } - - pub const Reader = std.io.Reader(File, anyerror, stdIoRead); - - pub fn reader(self: File) Reader { - return Reader{ .context = self }; - } - - pub const WriteError = anyerror; - fn stdIoWrite(this: File, bytes: []const u8) WriteError!usize { - try this.writeAll(bytes).unwrap(); - - return bytes.len; - } - - fn stdIoWriteQuietDebug(this: File, bytes: []const u8) WriteError!usize { - bun.Output.disableScopedDebugWriter(); - defer bun.Output.enableScopedDebugWriter(); - try this.writeAll(bytes).unwrap(); - - return bytes.len; - } - - pub const Writer = std.io.Writer(File, anyerror, stdIoWrite); - pub const QuietWriter = if (Environment.isDebug) std.io.Writer(File, anyerror, stdIoWriteQuietDebug) else Writer; - - pub fn writer(self: File) Writer { - return Writer{ .context = self }; - } - - pub fn quietWriter(self: File) QuietWriter { - return QuietWriter{ .context = self }; - } - - pub fn isTty(self: File) bool { - return std.posix.isatty(self.handle.cast()); - } - - /// Asserts in debug that this File object is valid - pub fn close(self: File) void { - self.handle.close(); - } - - pub fn getEndPos(self: File) Maybe(usize) { - return getFileSize(self.handle); - } - - pub fn stat(self: File) Maybe(bun.Stat) { - return fstat(self.handle); - } - - /// Be careful about using this on Linux or macOS. - /// - /// This calls stat() internally. - pub fn kind(self: File) Maybe(std.fs.File.Kind) { - if (Environment.isWindows) { - const rt = windows.GetFileType(self.handle.cast()); - if (rt == windows.FILE_TYPE_UNKNOWN) { - switch (windows.GetLastError()) { - .SUCCESS => {}, - else => |err| { - return .{ .err = Error.fromCode((SystemErrno.init(err) orelse SystemErrno.EUNKNOWN).toE(), .fstat) }; - }, - } - } - - return .{ - .result = switch (rt) { - windows.FILE_TYPE_CHAR => .character_device, - windows.FILE_TYPE_REMOTE, windows.FILE_TYPE_DISK => .file, - windows.FILE_TYPE_PIPE => .named_pipe, - windows.FILE_TYPE_UNKNOWN => .unknown, - else => .file, - }, - }; - } - - const st = switch (self.stat()) { - .err => |err| return .{ .err = err }, - .result => |s| s, - }; - - const m = st.mode & posix.S.IFMT; - switch (m) { - posix.S.IFBLK => return .{ .result = .block_device }, - posix.S.IFCHR => return .{ .result = .character_device }, - posix.S.IFDIR => return .{ .result = .directory }, - posix.S.IFIFO => return .{ .result = .named_pipe }, - posix.S.IFLNK => return .{ .result = .sym_link }, - posix.S.IFREG => return .{ .result = .file }, - posix.S.IFSOCK => return .{ .result = .unix_domain_socket }, - else => { - return .{ .result = .file }; - }, - } - } - - pub const ReadToEndResult = struct { - bytes: std.ArrayList(u8) = std.ArrayList(u8).init(default_allocator), - err: ?Error = null, - - pub fn unwrap(self: *const ReadToEndResult) ![]u8 { - if (self.err) |err| { - try (bun.sys.Maybe(void){ .err = err }).unwrap(); - } - return self.bytes.items; - } - }; - - pub fn readFillBuf(this: File, buf: []u8) Maybe([]u8) { - var read_amount: usize = 0; - while (read_amount < buf.len) { - switch (if (comptime Environment.isPosix) - pread(this.handle, buf[read_amount..], @intCast(read_amount)) - else - sys.read(this.handle, buf[read_amount..])) { - .err => |err| { - return .{ .err = err }; - }, - .result => |bytes_read| { - if (bytes_read == 0) { - break; - } - - read_amount += bytes_read; - }, - } - } - - return .{ .result = buf[0..read_amount] }; - } - - pub fn readToEndWithArrayList(this: File, list: *std.ArrayList(u8), probably_small: bool) Maybe(usize) { - if (probably_small) { - list.ensureUnusedCapacity(64) catch bun.outOfMemory(); - } else { - list.ensureTotalCapacityPrecise( - switch (this.getEndPos()) { - .err => |err| { - return .{ .err = err }; - }, - .result => |s| s, - } + 16, - ) catch bun.outOfMemory(); - } - - var total: i64 = 0; - while (true) { - if (list.unusedCapacitySlice().len == 0) { - list.ensureUnusedCapacity(16) catch bun.outOfMemory(); - } - - switch (if (comptime Environment.isPosix) - pread(this.handle, list.unusedCapacitySlice(), total) - else - sys.read(this.handle, list.unusedCapacitySlice())) { - .err => |err| { - return .{ .err = err }; - }, - .result => |bytes_read| { - if (bytes_read == 0) { - break; - } - - list.items.len += bytes_read; - total += @intCast(bytes_read); - }, - } - } - - return .{ .result = @intCast(total) }; - } - - /// Use this function on potentially large files. - /// Calls fstat() on the file to get the size of the file and avoids reallocations + extra read() calls. - pub fn readToEnd(this: File, allocator: std.mem.Allocator) ReadToEndResult { - var list = std.ArrayList(u8).init(allocator); - return switch (readToEndWithArrayList(this, &list, false)) { - .err => |err| .{ .err = err, .bytes = list }, - .result => .{ .err = null, .bytes = list }, - }; - } - - /// Use this function on small files <= 1024 bytes. - /// This will skip the fstat() call, preallocating 64 bytes instead of the file's size. - pub fn readToEndSmall(this: File, allocator: std.mem.Allocator) ReadToEndResult { - var list = std.ArrayList(u8).init(allocator); - return switch (readToEndWithArrayList(this, &list, true)) { - .err => |err| .{ .err = err, .bytes = list }, - .result => .{ .err = null, .bytes = list }, - }; - } - - pub fn getPath(this: File, out_buffer: *bun.PathBuffer) Maybe([]u8) { - return getFdPath(this.handle, out_buffer); - } - - /// 1. Normalize the file path - /// 2. Open a file for reading - /// 2. Read the file to a buffer - /// 3. Return the File handle and the buffer - pub fn readFromUserInput(dir_fd: anytype, input_path: anytype, allocator: std.mem.Allocator) Maybe([]u8) { - var buf: bun.PathBuffer = undefined; - const normalized = bun.path.joinAbsStringBufZ( - bun.fs.FileSystem.instance.top_level_dir, - &buf, - &.{input_path}, - .loose, - ); - return readFrom(dir_fd, normalized, allocator); - } - - /// 1. Open a file for reading - /// 2. Read the file to a buffer - /// 3. Return the File handle and the buffer - pub fn readFileFrom(dir_fd: anytype, path: anytype, allocator: std.mem.Allocator) Maybe(struct { File, []u8 }) { - const ElementType = std.meta.Elem(@TypeOf(path)); - - const rc = brk: { - if (comptime Environment.isWindows and ElementType == u16) { - break :brk openatWindowsTMaybeNormalize(u16, from(dir_fd).handle, path, O.RDONLY, false); - } - - if (comptime ElementType == u8 and std.meta.sentinel(@TypeOf(path)) == null) { - break :brk sys.openatA(from(dir_fd).handle, path, O.RDONLY, 0); - } - - break :brk sys.openat(from(dir_fd).handle, path, O.RDONLY, 0); - }; - - const this = switch (rc) { - .err => |err| return .{ .err = err }, - .result => |fd| from(fd), - }; - - var result = this.readToEnd(allocator); - - if (result.err) |err| { - this.close(); - result.bytes.deinit(); - return .{ .err = err }; - } - - if (result.bytes.items.len == 0) { - // Don't allocate an empty string. - // We won't be modifying an empty slice, anyway. - return .{ .result = .{ this, @ptrCast(@constCast("")) } }; - } - - return .{ .result = .{ this, result.bytes.items } }; - } - - /// 1. Open a file for reading relative to a directory - /// 2. Read the file to a buffer - /// 3. Close the file - /// 4. Return the buffer - pub fn readFrom(dir_fd: anytype, path: anytype, allocator: std.mem.Allocator) Maybe([]u8) { - const file, const bytes = switch (readFileFrom(dir_fd, path, allocator)) { - .err => |err| return .{ .err = err }, - .result => |result| result, - }; - - file.close(); - return .{ .result = bytes }; - } - - const ToSourceOptions = struct { - convert_bom: bool = false, - }; - - pub fn toSourceAt(dir_fd: anytype, path: anytype, allocator: std.mem.Allocator, opts: ToSourceOptions) Maybe(bun.logger.Source) { - var bytes = switch (readFrom(dir_fd, path, allocator)) { - .err => |err| return .{ .err = err }, - .result => |bytes| bytes, - }; - - if (opts.convert_bom) { - if (bun.strings.BOM.detect(bytes)) |bom| { - bytes = bom.removeAndConvertToUTF8AndFree(allocator, bytes) catch bun.outOfMemory(); - } - } - - return .{ .result = bun.logger.Source.initPathString(path, bytes) }; - } - - pub fn toSource(path: anytype, allocator: std.mem.Allocator, opts: ToSourceOptions) Maybe(bun.logger.Source) { - return toSourceAt(std.fs.cwd(), path, allocator, opts); - } -}; - pub const Dir = @import("./dir.zig"); const FILE_SHARE = w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE; -/// This map is derived off of uv.h's definitions, and is what Node.js uses in printing errors. -pub const libuv_error_map = brk: { - const entries: []const struct { [:0]const u8, [:0]const u8 } = &.{ - .{ "E2BIG", "argument list too long" }, - .{ "EACCES", "permission denied" }, - .{ "EADDRINUSE", "address already in use" }, - .{ "EADDRNOTAVAIL", "address not available" }, - .{ "EAFNOSUPPORT", "address family not supported" }, - .{ "EAGAIN", "resource temporarily unavailable" }, - .{ "EAI_ADDRFAMILY", "address family not supported" }, - .{ "EAI_AGAIN", "temporary failure" }, - .{ "EAI_BADFLAGS", "bad ai_flags value" }, - .{ "EAI_BADHINTS", "invalid value for hints" }, - .{ "EAI_CANCELED", "request canceled" }, - .{ "EAI_FAIL", "permanent failure" }, - .{ "EAI_FAMILY", "ai_family not supported" }, - .{ "EAI_MEMORY", "out of memory" }, - .{ "EAI_NODATA", "no address" }, - .{ "EAI_NONAME", "unknown node or service" }, - .{ "EAI_OVERFLOW", "argument buffer overflow" }, - .{ "EAI_PROTOCOL", "resolved protocol is unknown" }, - .{ "EAI_SERVICE", "service not available for socket type" }, - .{ "EAI_SOCKTYPE", "socket type not supported" }, - .{ "EALREADY", "connection already in progress" }, - .{ "EBADF", "bad file descriptor" }, - .{ "EBUSY", "resource busy or locked" }, - .{ "ECANCELED", "operation canceled" }, - .{ "ECHARSET", "invalid Unicode character" }, - .{ "ECONNABORTED", "software caused connection abort" }, - .{ "ECONNREFUSED", "connection refused" }, - .{ "ECONNRESET", "connection reset by peer" }, - .{ "EDESTADDRREQ", "destination address required" }, - .{ "EEXIST", "file already exists" }, - .{ "EFAULT", "bad address in system call argument" }, - .{ "EFBIG", "file too large" }, - .{ "EHOSTUNREACH", "host is unreachable" }, - .{ "EINTR", "interrupted system call" }, - .{ "EINVAL", "invalid argument" }, - .{ "EIO", "i/o error" }, - .{ "EISCONN", "socket is already connected" }, - .{ "EISDIR", "illegal operation on a directory" }, - .{ "ELOOP", "too many symbolic links encountered" }, - .{ "EMFILE", "too many open files" }, - .{ "EMSGSIZE", "message too long" }, - .{ "ENAMETOOLONG", "name too long" }, - .{ "ENETDOWN", "network is down" }, - .{ "ENETUNREACH", "network is unreachable" }, - .{ "ENFILE", "file table overflow" }, - .{ "ENOBUFS", "no buffer space available" }, - .{ "ENODEV", "no such device" }, - .{ "ENOENT", "no such file or directory" }, - .{ "ENOMEM", "not enough memory" }, - .{ "ENONET", "machine is not on the network" }, - .{ "ENOPROTOOPT", "protocol not available" }, - .{ "ENOSPC", "no space left on device" }, - .{ "ENOSYS", "function not implemented" }, - .{ "ENOTCONN", "socket is not connected" }, - .{ "ENOTDIR", "not a directory" }, - .{ "ENOTEMPTY", "directory not empty" }, - .{ "ENOTSOCK", "socket operation on non-socket" }, - .{ "ENOTSUP", "operation not supported on socket" }, - .{ "EOVERFLOW", "value too large for defined data type" }, - .{ "EPERM", "operation not permitted" }, - .{ "EPIPE", "broken pipe" }, - .{ "EPROTO", "protocol error" }, - .{ "EPROTONOSUPPORT", "protocol not supported" }, - .{ "EPROTOTYPE", "protocol wrong type for socket" }, - .{ "ERANGE", "result too large" }, - .{ "EROFS", "read-only file system" }, - .{ "ESHUTDOWN", "cannot send after transport endpoint shutdown" }, - .{ "ESPIPE", "invalid seek" }, - .{ "ESRCH", "no such process" }, - .{ "ETIMEDOUT", "connection timed out" }, - .{ "ETXTBSY", "text file is busy" }, - .{ "EXDEV", "cross-device link not permitted" }, - .{ "UNKNOWN", "unknown error" }, - .{ "EOF", "end of file" }, - .{ "ENXIO", "no such device or address" }, - .{ "EMLINK", "too many links" }, - .{ "EHOSTDOWN", "host is down" }, - .{ "EREMOTEIO", "remote I/O error" }, - .{ "ENOTTY", "inappropriate ioctl for device" }, - .{ "EFTYPE", "inappropriate file type or format" }, - .{ "EILSEQ", "illegal byte sequence" }, - .{ "ESOCKTNOSUPPORT", "socket type not supported" }, - .{ "ENODATA", "no data available" }, - .{ "EUNATCH", "protocol driver not attached" }, - }; - var map = std.EnumMap(SystemErrno, [:0]const u8).initFull("unknown error"); - for (entries) |entry| { - const key, const text = entry; - if (@hasField(SystemErrno, key)) { - map.put(@field(SystemErrno, key), text); - } - } - - // sanity check - bun.assert(std.mem.eql(u8, map.get(SystemErrno.ENOENT).?, "no such file or directory")); - - break :brk map; -}; - -/// This map is derived off of what coreutils uses in printing errors. This is -/// equivalent to `strerror`, but as strings with constant lifetime. -pub const coreutils_error_map = brk: { - // macOS and Linux have slightly different error messages. - const entries: []const struct { [:0]const u8, [:0]const u8 } = switch (Environment.os) { - // Since windows is just an emulation of linux, it will derive the linux error messages. - .linux, .windows, .wasm => &.{ - .{ "EPERM", "Operation not permitted" }, - .{ "ENOENT", "No such file or directory" }, - .{ "ESRCH", "No such process" }, - .{ "EINTR", "Interrupted system call" }, - .{ "EIO", "Input/output error" }, - .{ "ENXIO", "No such device or address" }, - .{ "E2BIG", "Argument list too long" }, - .{ "ENOEXEC", "Exec format error" }, - .{ "EBADF", "Bad file descriptor" }, - .{ "ECHILD", "No child processes" }, - .{ "EAGAIN", "Resource temporarily unavailable" }, - .{ "ENOMEM", "Cannot allocate memory" }, - .{ "EACCES", "Permission denied" }, - .{ "EFAULT", "Bad address" }, - .{ "ENOTBLK", "Block device required" }, - .{ "EBUSY", "Device or resource busy" }, - .{ "EEXIST", "File exists" }, - .{ "EXDEV", "Invalid cross-device link" }, - .{ "ENODEV", "No such device" }, - .{ "ENOTDIR", "Not a directory" }, - .{ "EISDIR", "Is a directory" }, - .{ "EINVAL", "Invalid argument" }, - .{ "ENFILE", "Too many open files in system" }, - .{ "EMFILE", "Too many open files" }, - .{ "ENOTTY", "Inappropriate ioctl for device" }, - .{ "ETXTBSY", "Text file busy" }, - .{ "EFBIG", "File too large" }, - .{ "ENOSPC", "No space left on device" }, - .{ "ESPIPE", "Illegal seek" }, - .{ "EROFS", "Read-only file system" }, - .{ "EMLINK", "Too many links" }, - .{ "EPIPE", "Broken pipe" }, - .{ "EDOM", "Numerical argument out of domain" }, - .{ "ERANGE", "Numerical result out of range" }, - .{ "EDEADLK", "Resource deadlock avoided" }, - .{ "ENAMETOOLONG", "File name too long" }, - .{ "ENOLCK", "No locks available" }, - .{ "ENOSYS", "Function not implemented" }, - .{ "ENOTEMPTY", "Directory not empty" }, - .{ "ELOOP", "Too many levels of symbolic links" }, - .{ "ENOMSG", "No message of desired type" }, - .{ "EIDRM", "Identifier removed" }, - .{ "ECHRNG", "Channel number out of range" }, - .{ "EL2NSYNC", "Level 2 not synchronized" }, - .{ "EL3HLT", "Level 3 halted" }, - .{ "EL3RST", "Level 3 reset" }, - .{ "ELNRNG", "Link number out of range" }, - .{ "EUNATCH", "Protocol driver not attached" }, - .{ "ENOCSI", "No CSI structure available" }, - .{ "EL2HLT", "Level 2 halted" }, - .{ "EBADE", "Invalid exchange" }, - .{ "EBADR", "Invalid request descriptor" }, - .{ "EXFULL", "Exchange full" }, - .{ "ENOANO", "No anode" }, - .{ "EBADRQC", "Invalid request code" }, - .{ "EBADSLT", "Invalid slot" }, - .{ "EBFONT", "Bad font file format" }, - .{ "ENOSTR", "Device not a stream" }, - .{ "ENODATA", "No data available" }, - .{ "ETIME", "Timer expired" }, - .{ "ENOSR", "Out of streams resources" }, - .{ "ENONET", "Machine is not on the network" }, - .{ "ENOPKG", "Package not installed" }, - .{ "EREMOTE", "Object is remote" }, - .{ "ENOLINK", "Link has been severed" }, - .{ "EADV", "Advertise error" }, - .{ "ESRMNT", "Srmount error" }, - .{ "ECOMM", "Communication error on send" }, - .{ "EPROTO", "Protocol error" }, - .{ "EMULTIHOP", "Multihop attempted" }, - .{ "EDOTDOT", "RFS specific error" }, - .{ "EBADMSG", "Bad message" }, - .{ "EOVERFLOW", "Value too large for defined data type" }, - .{ "ENOTUNIQ", "Name not unique on network" }, - .{ "EBADFD", "File descriptor in bad state" }, - .{ "EREMCHG", "Remote address changed" }, - .{ "ELIBACC", "Can not access a needed shared library" }, - .{ "ELIBBAD", "Accessing a corrupted shared library" }, - .{ "ELIBSCN", ".lib section in a.out corrupted" }, - .{ "ELIBMAX", "Attempting to link in too many shared libraries" }, - .{ "ELIBEXEC", "Cannot exec a shared library directly" }, - .{ "EILSEQ", "Invalid or incomplete multibyte or wide character" }, - .{ "ERESTART", "Interrupted system call should be restarted" }, - .{ "ESTRPIPE", "Streams pipe error" }, - .{ "EUSERS", "Too many users" }, - .{ "ENOTSOCK", "Socket operation on non-socket" }, - .{ "EDESTADDRREQ", "Destination address required" }, - .{ "EMSGSIZE", "Message too long" }, - .{ "EPROTOTYPE", "Protocol wrong type for socket" }, - .{ "ENOPROTOOPT", "Protocol not available" }, - .{ "EPROTONOSUPPORT", "Protocol not supported" }, - .{ "ESOCKTNOSUPPORT", "Socket type not supported" }, - .{ "EOPNOTSUPP", "Operation not supported" }, - .{ "EPFNOSUPPORT", "Protocol family not supported" }, - .{ "EAFNOSUPPORT", "Address family not supported by protocol" }, - .{ "EADDRINUSE", "Address already in use" }, - .{ "EADDRNOTAVAIL", "Cannot assign requested address" }, - .{ "ENETDOWN", "Network is down" }, - .{ "ENETUNREACH", "Network is unreachable" }, - .{ "ENETRESET", "Network dropped connection on reset" }, - .{ "ECONNABORTED", "Software caused connection abort" }, - .{ "ECONNRESET", "Connection reset by peer" }, - .{ "ENOBUFS", "No buffer space available" }, - .{ "EISCONN", "Transport endpoint is already connected" }, - .{ "ENOTCONN", "Transport endpoint is not connected" }, - .{ "ESHUTDOWN", "Cannot send after transport endpoint shutdown" }, - .{ "ETOOMANYREFS", "Too many references: cannot splice" }, - .{ "ETIMEDOUT", "Connection timed out" }, - .{ "ECONNREFUSED", "Connection refused" }, - .{ "EHOSTDOWN", "Host is down" }, - .{ "EHOSTUNREACH", "No route to host" }, - .{ "EALREADY", "Operation already in progress" }, - .{ "EINPROGRESS", "Operation now in progress" }, - .{ "ESTALE", "Stale file handle" }, - .{ "EUCLEAN", "Structure needs cleaning" }, - .{ "ENOTNAM", "Not a XENIX named type file" }, - .{ "ENAVAIL", "No XENIX semaphores available" }, - .{ "EISNAM", "Is a named type file" }, - .{ "EREMOTEIO", "Remote I/O error" }, - .{ "EDQUOT", "Disk quota exceeded" }, - .{ "ENOMEDIUM", "No medium found" }, - .{ "EMEDIUMTYPE", "Wrong medium type" }, - .{ "ECANCELED", "Operation canceled" }, - .{ "ENOKEY", "Required key not available" }, - .{ "EKEYEXPIRED", "Key has expired" }, - .{ "EKEYREVOKED", "Key has been revoked" }, - .{ "EKEYREJECTED", "Key was rejected by service" }, - .{ "EOWNERDEAD", "Owner died" }, - .{ "ENOTRECOVERABLE", "State not recoverable" }, - .{ "ERFKILL", "Operation not possible due to RF-kill" }, - .{ "EHWPOISON", "Memory page has hardware error" }, - }, - // Mac has slightly different messages. To keep it consistent with bash/coreutils, - // it will use those altered messages. - .mac => &.{ - .{ "E2BIG", "Argument list too long" }, - .{ "EACCES", "Permission denied" }, - .{ "EADDRINUSE", "Address already in use" }, - .{ "EADDRNOTAVAIL", "Can't assign requested address" }, - .{ "EAFNOSUPPORT", "Address family not supported by protocol family" }, - .{ "EAGAIN", "non-blocking and interrupt i/o. Resource temporarily unavailable" }, - .{ "EALREADY", "Operation already in progress" }, - .{ "EAUTH", "Authentication error" }, - .{ "EBADARCH", "Bad CPU type in executable" }, - .{ "EBADEXEC", "Program loading errors. Bad executable" }, - .{ "EBADF", "Bad file descriptor" }, - .{ "EBADMACHO", "Malformed Macho file" }, - .{ "EBADMSG", "Bad message" }, - .{ "EBADRPC", "RPC struct is bad" }, - .{ "EBUSY", "Device / Resource busy" }, - .{ "ECANCELED", "Operation canceled" }, - .{ "ECHILD", "No child processes" }, - .{ "ECONNABORTED", "Software caused connection abort" }, - .{ "ECONNREFUSED", "Connection refused" }, - .{ "ECONNRESET", "Connection reset by peer" }, - .{ "EDEADLK", "Resource deadlock avoided" }, - .{ "EDESTADDRREQ", "Destination address required" }, - .{ "EDEVERR", "Device error, for example paper out" }, - .{ "EDOM", "math software. Numerical argument out of domain" }, - .{ "EDQUOT", "Disc quota exceeded" }, - .{ "EEXIST", "File or folder exists" }, - .{ "EFAULT", "Bad address" }, - .{ "EFBIG", "File too large" }, - .{ "EFTYPE", "Inappropriate file type or format" }, - .{ "EHOSTDOWN", "Host is down" }, - .{ "EHOSTUNREACH", "No route to host" }, - .{ "EIDRM", "Identifier removed" }, - .{ "EILSEQ", "Illegal byte sequence" }, - .{ "EINPROGRESS", "Operation now in progress" }, - .{ "EINTR", "Interrupted system call" }, - .{ "EINVAL", "Invalid argument" }, - .{ "EIO", "Input/output error" }, - .{ "EISCONN", "Socket is already connected" }, - .{ "EISDIR", "Is a directory" }, - .{ "ELOOP", "Too many levels of symbolic links" }, - .{ "EMFILE", "Too many open files" }, - .{ "EMLINK", "Too many links" }, - .{ "EMSGSIZE", "Message too long" }, - .{ "EMULTIHOP", "Reserved" }, - .{ "ENAMETOOLONG", "File name too long" }, - .{ "ENEEDAUTH", "Need authenticator" }, - .{ "ENETDOWN", "ipc/network software - operational errors Network is down" }, - .{ "ENETRESET", "Network dropped connection on reset" }, - .{ "ENETUNREACH", "Network is unreachable" }, - .{ "ENFILE", "Too many open files in system" }, - .{ "ENOATTR", "Attribute not found" }, - .{ "ENOBUFS", "No buffer space available" }, - .{ "ENODATA", "No message available on STREAM" }, - .{ "ENODEV", "Operation not supported by device" }, - .{ "ENOENT", "No such file or directory" }, - .{ "ENOEXEC", "Exec format error" }, - .{ "ENOLCK", "No locks available" }, - .{ "ENOLINK", "Reserved" }, - .{ "ENOMEM", "Out of memory" }, - .{ "ENOMSG", "No message of desired type" }, - .{ "ENOPOLICY", "No such policy registered" }, - .{ "ENOPROTOOPT", "Protocol not available" }, - .{ "ENOSPC", "No space left on device" }, - .{ "ENOSR", "No STREAM resources" }, - .{ "ENOSTR", "Not a STREAM" }, - .{ "ENOSYS", "Function not implemented" }, - .{ "ENOTBLK", "Block device required" }, - .{ "ENOTCONN", "Socket is not connected" }, - .{ "ENOTDIR", "Not a directory" }, - .{ "ENOTEMPTY", "Directory not empty" }, - .{ "ENOTRECOVERABLE", "State not recoverable" }, - .{ "ENOTSOCK", "ipc/network software - argument errors. Socket operation on non-socket" }, - .{ "ENOTSUP", "Operation not supported" }, - .{ "ENOTTY", "Inappropriate ioctl for device" }, - .{ "ENXIO", "Device not configured" }, - .{ "EOVERFLOW", "Value too large to be stored in data type" }, - .{ "EOWNERDEAD", "Previous owner died" }, - .{ "EPERM", "Operation not permitted" }, - .{ "EPFNOSUPPORT", "Protocol family not supported" }, - .{ "EPIPE", "Broken pipe" }, - .{ "EPROCLIM", "quotas & mush. Too many processes" }, - .{ "EPROCUNAVAIL", "Bad procedure for program" }, - .{ "EPROGMISMATCH", "Program version wrong" }, - .{ "EPROGUNAVAIL", "RPC prog. not avail" }, - .{ "EPROTO", "Protocol error" }, - .{ "EPROTONOSUPPORT", "Protocol not supported" }, - .{ "EPROTOTYPE", "Protocol wrong type for socket" }, - .{ "EPWROFF", "Intelligent device errors. Device power is off" }, - .{ "EQFULL", "Interface output queue is full" }, - .{ "ERANGE", "Result too large" }, - .{ "EREMOTE", "Too many levels of remote in path" }, - .{ "EROFS", "Read-only file system" }, - .{ "ERPCMISMATCH", "RPC version wrong" }, - .{ "ESHLIBVERS", "Shared library version mismatch" }, - .{ "ESHUTDOWN", "Can't send after socket shutdown" }, - .{ "ESOCKTNOSUPPORT", "Socket type not supported" }, - .{ "ESPIPE", "Illegal seek" }, - .{ "ESRCH", "No such process" }, - .{ "ESTALE", "Network File System. Stale NFS file handle" }, - .{ "ETIME", "STREAM ioctl timeout" }, - .{ "ETIMEDOUT", "Operation timed out" }, - .{ "ETOOMANYREFS", "Too many references: can't splice" }, - .{ "ETXTBSY", "Text file busy" }, - .{ "EUSERS", "Too many users" }, - .{ "EWOULDBLOCK", "Operation would block" }, - .{ "EXDEV", "Cross-device link" }, - }, - }; - - var map = std.EnumMap(SystemErrno, [:0]const u8).initFull("unknown error"); - for (entries) |entry| { - const key, const text = entry; - if (@hasField(SystemErrno, key)) { - map.put(@field(SystemErrno, key), text); - } - } - - // sanity check - bun.assert(std.mem.eql(u8, map.get(SystemErrno.ENOENT).?, "No such file or directory")); - - break :brk map; -}; +pub const libuv_error_map = @import("./sys/libuv_error_map.zig").libuv_error_map; +pub const coreutils_error_map = @import("./sys/coreutils_error_map.zig").coreutils_error_map; extern fn getRSS(rss: *usize) c_int; pub fn selfProcessMemoryUsage() ?usize { @@ -5233,6 +4116,8 @@ pub const umask = switch (Environment.os) { .windows => @extern(*const fn (mode: u16) callconv(.c) u16, .{ .name = "_umask" }), }; +pub const File = @import("./sys/File.zig"); + const builtin = @import("builtin"); const sys = @This(); // to avoid ambiguous references. @@ -5241,14 +4126,11 @@ const Environment = bun.Environment; const FD = bun.FD; const MAX_PATH_BYTES = bun.MAX_PATH_BYTES; const c = bun.c; // translated c headers -const default_allocator = bun.default_allocator; +const jsc = bun.jsc; const libc_stat = bun.Stat; const assertIsValidWindowsPath = bun.strings.assertIsValidWindowsPath; const darwin_nocancel = bun.darwin.nocancel; -const jsc = bun.jsc; -const SystemError = jsc.SystemError; - const windows = bun.windows; const kernel32 = bun.windows.kernel32; const ntdll = bun.windows.ntdll; diff --git a/src/sys/Error.zig b/src/sys/Error.zig new file mode 100644 index 0000000000..a5fae58431 --- /dev/null +++ b/src/sys/Error.zig @@ -0,0 +1,341 @@ +//! Error type that preserves useful information from the operating system +const Error = @This(); + +const retry_errno = if (Environment.isLinux) + @as(Int, @intCast(@intFromEnum(E.AGAIN))) +else if (Environment.isMac) + @as(Int, @intCast(@intFromEnum(E.AGAIN))) +else + @as(Int, @intCast(@intFromEnum(E.INTR))); + +const todo_errno = std.math.maxInt(Int) - 1; + +pub const Int = u16; + +/// TODO: convert to function +pub const oom = fromCode(E.NOMEM, .read); + +errno: Int = todo_errno, +fd: bun.FileDescriptor = bun.invalid_fd, +from_libuv: if (Environment.isWindows) bool else void = if (Environment.isWindows) false else undefined, +path: []const u8 = "", +syscall: sys.Tag = sys.Tag.TODO, +dest: []const u8 = "", + +pub fn clone(this: *const Error, allocator: std.mem.Allocator) Error { + var copy = this.*; + copy.path = allocator.dupe(u8, copy.path) catch bun.outOfMemory(); + copy.dest = allocator.dupe(u8, copy.dest) catch bun.outOfMemory(); + return copy; +} + +pub fn fromCode(errno: E, syscall_tag: sys.Tag) Error { + return .{ + .errno = @as(Int, @intCast(@intFromEnum(errno))), + .syscall = syscall_tag, + }; +} + +pub fn fromCodeInt(errno: anytype, syscall_tag: sys.Tag) Error { + return .{ + .errno = @as(Int, @intCast(if (Environment.isWindows) @abs(errno) else errno)), + .syscall = syscall_tag, + }; +} + +pub fn format(self: Error, comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void { + // We want to reuse the code from SystemError for formatting. + // But, we do not want to call String.createUTF8 on the path/dest strings + // because we're intending to pass them to writer.print() + // which will convert them back into UTF*. + var that = self.withoutPath().toShellSystemError(); + bun.debugAssert(that.path.tag != .WTFStringImpl); + bun.debugAssert(that.dest.tag != .WTFStringImpl); + that.path = bun.String.borrowUTF8(self.path); + that.dest = bun.String.borrowUTF8(self.dest); + bun.debugAssert(that.path.tag != .WTFStringImpl); + bun.debugAssert(that.dest.tag != .WTFStringImpl); + + return that.format(fmt, opts, writer); +} + +pub inline fn getErrno(this: Error) E { + return @as(E, @enumFromInt(this.errno)); +} + +pub inline fn isRetry(this: *const Error) bool { + return this.getErrno() == .AGAIN; +} + +pub const retry = Error{ + .errno = retry_errno, + .syscall = .read, +}; + +pub inline fn withFd(this: Error, fd: anytype) Error { + if (Environment.allow_assert) bun.assert(fd != bun.invalid_fd); + return Error{ + .errno = this.errno, + .syscall = this.syscall, + .fd = fd, + }; +} + +pub inline fn withPath(this: Error, path: anytype) Error { + if (std.meta.Child(@TypeOf(path)) == u16) { + @compileError("Do not pass WString path to withPath, it needs the path encoded as utf8"); + } + return Error{ + .errno = this.errno, + .syscall = this.syscall, + .path = bun.span(path), + }; +} + +pub inline fn withPathAndSyscall(this: Error, path: anytype, syscall_: sys.Tag) Error { + if (std.meta.Child(@TypeOf(path)) == u16) { + @compileError("Do not pass WString path to withPath, it needs the path encoded as utf8"); + } + return Error{ + .errno = this.errno, + .syscall = syscall_, + .path = bun.span(path), + }; +} + +pub fn deinit(this: *Error) void { + this.deinitWithAllocator(bun.default_allocator); +} + +/// Only call this after it's been .clone()'d +pub fn deinitWithAllocator(this: *Error, allocator: std.mem.Allocator) void { + if (this.path.len > 0) { + allocator.free(this.path); + this.path = ""; + } + if (this.dest.len > 0) { + allocator.free(this.dest); + this.dest = ""; + } +} + +pub inline fn withPathDest(this: Error, path: anytype, dest: anytype) Error { + if (std.meta.Child(@TypeOf(path)) == u16) { + @compileError("Do not pass WString path to withPathDest, it needs the path encoded as utf8 (path)"); + } + if (std.meta.Child(@TypeOf(dest)) == u16) { + @compileError("Do not pass WString path to withPathDest, it needs the path encoded as utf8 (dest)"); + } + return Error{ + .errno = this.errno, + .syscall = this.syscall, + .path = bun.span(path), + .dest = bun.span(dest), + }; +} + +pub inline fn withPathLike(this: Error, pathlike: anytype) Error { + return switch (pathlike) { + .fd => |fd| this.withFd(fd), + .path => |path| this.withPath(path.slice()), + }; +} + +/// When the memory of the path/dest buffer is unsafe to use, call this function to clone the error without the path/dest. +pub fn withoutPath(this: *const Error) Error { + var copy = this.*; + copy.path = ""; + copy.dest = ""; + return copy; +} + +pub fn name(this: *const Error) []const u8 { + if (comptime Environment.isWindows) { + const system_errno = brk: { + // setRuntimeSafety(false) because we use tagName function, which will be null on invalid enum value. + @setRuntimeSafety(false); + if (this.from_libuv) { + break :brk @as(SystemErrno, @enumFromInt(@intFromEnum(bun.windows.libuv.translateUVErrorToE(this.errno)))); + } + + break :brk @as(SystemErrno, @enumFromInt(this.errno)); + }; + if (bun.tagName(SystemErrno, system_errno)) |errname| { + return errname; + } + } else if (this.errno > 0 and this.errno < SystemErrno.max) { + const system_errno = @as(SystemErrno, @enumFromInt(this.errno)); + if (bun.tagName(SystemErrno, system_errno)) |errname| { + return errname; + } + } + + return "UNKNOWN"; +} + +pub fn toZigErr(this: Error) anyerror { + return bun.errnoToZigErr(this.errno); +} + +/// 1. Convert libuv errno values into libc ones. +/// 2. Get the tag name as a string for printing. +pub fn getErrorCodeTagName(err: *const Error) ?struct { [:0]const u8, SystemErrno } { + if (!Environment.isWindows) { + if (err.errno > 0 and err.errno < SystemErrno.max) { + const system_errno = @as(SystemErrno, @enumFromInt(err.errno)); + return .{ @tagName(system_errno), system_errno }; + } + } else { + const system_errno: SystemErrno = brk: { + // setRuntimeSafety(false) because we use tagName function, which will be null on invalid enum value. + @setRuntimeSafety(false); + if (err.from_libuv) { + break :brk @enumFromInt(@intFromEnum(bun.windows.libuv.translateUVErrorToE(@as(c_int, err.errno) * -1))); + } + + break :brk @enumFromInt(err.errno); + }; + if (bun.tagName(SystemErrno, system_errno)) |errname| { + return .{ errname, system_errno }; + } + } + return null; +} + +pub fn msg(this: Error) ?[]const u8 { + if (this.getErrorCodeTagName()) |resolved_errno| { + const code, const system_errno = resolved_errno; + if (coreutils_error_map.get(system_errno)) |label| { + return label; + } + return code; + } + return null; +} + +/// Simpler formatting which does not allocate a message +pub fn toShellSystemError(this: Error) SystemError { + @setEvalBranchQuota(1_000_000); + var err = SystemError{ + .errno = @as(c_int, this.errno) * -1, + .syscall = bun.String.static(@tagName(this.syscall)), + .message = .empty, + }; + + // errno label + if (this.getErrorCodeTagName()) |resolved_errno| { + const code, const system_errno = resolved_errno; + err.code = bun.String.static(code); + if (coreutils_error_map.get(system_errno)) |label| { + err.message = bun.String.static(label); + } + } + + if (this.path.len > 0) { + err.path = bun.String.cloneUTF8(this.path); + } + + if (this.dest.len > 0) { + err.dest = bun.String.cloneUTF8(this.dest); + } + + if (this.fd.unwrapValid()) |valid| { + // When the FD is a windows handle, there is no sane way to report this. + if (!Environment.isWindows or valid.kind == .uv) { + err.fd = valid.uv(); + } + } + + return err; +} + +/// More complex formatting to precisely match the printing that Node.js emits. +/// Use this whenever the error will be sent to JavaScript instead of the shell variant above. +pub fn toSystemError(this: Error) SystemError { + var err = SystemError{ + .errno = -%@as(c_int, this.errno), + .syscall = bun.String.static(@tagName(this.syscall)), + .message = .empty, + }; + + // errno label + var maybe_code: ?[:0]const u8 = null; + var label: ?[]const u8 = null; + if (this.getErrorCodeTagName()) |resolved_errno| { + maybe_code, const system_errno = resolved_errno; + err.code = bun.String.static(maybe_code.?); + label = libuv_error_map.get(system_errno); + } + + // format taken from Node.js 'exceptions.cc' + // search keyword: `Local UVException(Isolate* isolate,` + var message_buf: [4096]u8 = @splat(0); + const message = message: { + var stream = std.io.fixedBufferStream(&message_buf); + const writer = stream.writer(); + brk: { + if (maybe_code) |code| { + writer.writeAll(code) catch break :brk; + writer.writeAll(": ") catch break :brk; + } + writer.writeAll(label orelse "Unknown Error") catch break :brk; + writer.writeAll(", ") catch break :brk; + writer.writeAll(@tagName(this.syscall)) catch break :brk; + if (this.path.len > 0) { + writer.writeAll(" '") catch break :brk; + writer.writeAll(this.path) catch break :brk; + writer.writeAll("'") catch break :brk; + + if (this.dest.len > 0) { + writer.writeAll(" -> '") catch break :brk; + writer.writeAll(this.dest) catch break :brk; + writer.writeAll("'") catch break :brk; + } + } + } + break :message stream.getWritten(); + }; + err.message = bun.String.cloneUTF8(message); + + if (this.path.len > 0) { + err.path = bun.String.cloneUTF8(this.path); + } + + if (this.dest.len > 0) { + err.dest = bun.String.cloneUTF8(this.dest); + } + + if (this.fd.unwrapValid()) |valid| { + // When the FD is a windows handle, there is no sane way to report this. + if (!Environment.isWindows or valid.kind == .uv) { + err.fd = valid.uv(); + } + } + + return err; +} + +pub inline fn todo() Error { + if (Environment.isDebug) { + @panic("Error.todo() was called"); + } + return Error{ .errno = todo_errno, .syscall = .TODO }; +} + +pub fn toJS(this: Error, ptr: *jsc.JSGlobalObject) jsc.JSValue { + return this.toSystemError().toErrorInstance(ptr); +} + +const std = @import("std"); + +const bun = @import("bun"); +const Environment = bun.Environment; + +const jsc = bun.jsc; +const SystemError = jsc.SystemError; + +const sys = bun.sys; +const E = sys.E; +const SystemErrno = sys.SystemErrno; +const coreutils_error_map = sys.coreutils_error_map; +const libuv_error_map = sys.libuv_error_map; diff --git a/src/sys/File.zig b/src/sys/File.zig new file mode 100644 index 0000000000..aa0abe7b80 --- /dev/null +++ b/src/sys/File.zig @@ -0,0 +1,452 @@ +//! This is a similar API to std.fs.File, except it: +//! - Preserves errors from the operating system +//! - Supports normalizing BOM to UTF-8 +//! - Has several optimizations somewhat specific to Bun +//! - Potentially goes through libuv on Windows +//! - Does not use unreachable in system calls. + +const File = @This(); + +// "handle" matches std.fs.File +handle: bun.FileDescriptor, + +pub fn openat(dir: bun.FileDescriptor, path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { + return switch (sys.openat(dir, path, flags, mode)) { + .result => |fd| .{ .result = .{ .handle = fd } }, + .err => |err| .{ .err = err }, + }; +} + +pub fn open(path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { + return File.openat(bun.FD.cwd(), path, flags, mode); +} + +pub fn makeOpen(path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { + return File.makeOpenat(bun.FD.cwd(), path, flags, mode); +} + +pub fn makeOpenat(other: bun.FD, path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { + const fd = switch (sys.openat(other, path, flags, mode)) { + .result => |fd| fd, + .err => |err| fd: { + if (std.fs.path.dirname(path)) |dir_path| { + bun.makePath(other.stdDir(), dir_path) catch {}; + break :fd switch (sys.openat(other, path, flags, mode)) { + .result => |fd| fd, + .err => |err2| return .{ .err = err2 }, + }; + } + + return .{ .err = err }; + }, + }; + + return .{ .result = .{ .handle = fd } }; +} + +pub fn openatOSPath(other: bun.FD, path: bun.OSPathSliceZ, flags: i32, mode: bun.Mode) Maybe(File) { + return switch (sys.openatOSPath(other, path, flags, mode)) { + .result => |fd| .{ .result = .{ .handle = fd } }, + .err => |err| .{ .err = err }, + }; +} + +pub fn from(other: anytype) File { + const T = @TypeOf(other); + + if (T == File) { + return other; + } + + if (T == std.posix.fd_t) { + return .{ .handle = .fromNative(other) }; + } + + if (T == bun.FileDescriptor) { + return .{ .handle = other }; + } + + if (T == std.fs.File) { + return .{ .handle = .fromStdFile(other) }; + } + + if (T == std.fs.Dir) { + return File{ .handle = .fromStdDir(other) }; + } + + if (comptime Environment.isLinux) { + if (T == u64) { + return File{ .handle = .fromNative(@intCast(other)) }; + } + } + + @compileError("Unsupported type " ++ bun.meta.typeName(T)); +} + +pub fn write(self: File, buf: []const u8) Maybe(usize) { + return sys.write(self.handle, buf); +} + +pub fn read(self: File, buf: []u8) Maybe(usize) { + return sys.read(self.handle, buf); +} + +pub fn readAll(self: File, buf: []u8) Maybe(usize) { + return sys.readAll(self.handle, buf); +} + +pub fn writeAll(self: File, buf: []const u8) Maybe(void) { + var remain = buf; + while (remain.len > 0) { + const rc = sys.write(self.handle, remain); + switch (rc) { + .err => |err| return .{ .err = err }, + .result => |amt| { + if (amt == 0) { + return .success; + } + remain = remain[amt..]; + }, + } + } + + return .success; +} + +pub fn writeFile( + relative_dir_or_cwd: anytype, + path: bun.OSPathSliceZ, + data: []const u8, +) Maybe(void) { + const file = switch (File.openatOSPath(relative_dir_or_cwd, path, bun.O.WRONLY | bun.O.CREAT | bun.O.TRUNC, 0o664)) { + .err => |err| return .{ .err = err }, + .result => |fd| fd, + }; + defer file.close(); + switch (file.writeAll(data)) { + .err => |err| return .{ .err = err }, + .result => {}, + } + return .success; +} + +pub const ReadError = anyerror; + +pub fn closeAndMoveTo(this: File, src: [:0]const u8, dest: [:0]const u8) !void { + // On POSIX, close the file after moving it. + defer if (Environment.isPosix) this.close(); + // On Windows, close the file before moving it. + if (Environment.isWindows) this.close(); + const cwd = bun.FD.cwd(); + try bun.sys.moveFileZWithHandle(this.handle, cwd, src, cwd, dest); +} + +fn stdIoRead(this: File, buf: []u8) ReadError!usize { + return try this.read(buf).unwrap(); +} + +pub const Reader = std.io.Reader(File, anyerror, stdIoRead); + +pub fn reader(self: File) Reader { + return Reader{ .context = self }; +} + +pub const WriteError = anyerror; +fn stdIoWrite(this: File, bytes: []const u8) WriteError!usize { + try this.writeAll(bytes).unwrap(); + + return bytes.len; +} + +fn stdIoWriteQuietDebug(this: File, bytes: []const u8) WriteError!usize { + bun.Output.disableScopedDebugWriter(); + defer bun.Output.enableScopedDebugWriter(); + try this.writeAll(bytes).unwrap(); + + return bytes.len; +} + +pub const Writer = std.io.Writer(File, anyerror, stdIoWrite); +pub const QuietWriter = if (Environment.isDebug) std.io.Writer(File, anyerror, stdIoWriteQuietDebug) else Writer; + +pub fn writer(self: File) Writer { + return Writer{ .context = self }; +} + +pub fn quietWriter(self: File) QuietWriter { + return QuietWriter{ .context = self }; +} + +pub fn isTty(self: File) bool { + return std.posix.isatty(self.handle.cast()); +} + +/// Asserts in debug that this File object is valid +pub fn close(self: File) void { + self.handle.close(); +} + +pub fn getEndPos(self: File) Maybe(usize) { + return getFileSize(self.handle); +} + +pub fn stat(self: File) Maybe(bun.Stat) { + return fstat(self.handle); +} + +/// Be careful about using this on Linux or macOS. +/// +/// File calls stat() internally. +pub fn kind(self: File) Maybe(std.fs.File.Kind) { + if (Environment.isWindows) { + const rt = windows.GetFileType(self.handle.cast()); + if (rt == windows.FILE_TYPE_UNKNOWN) { + switch (windows.GetLastError()) { + .SUCCESS => {}, + else => |err| { + return .{ .err = Error.fromCode((SystemErrno.init(err) orelse SystemErrno.EUNKNOWN).toE(), .fstat) }; + }, + } + } + + return .{ + .result = switch (rt) { + windows.FILE_TYPE_CHAR => .character_device, + windows.FILE_TYPE_REMOTE, windows.FILE_TYPE_DISK => .file, + windows.FILE_TYPE_PIPE => .named_pipe, + windows.FILE_TYPE_UNKNOWN => .unknown, + else => .file, + }, + }; + } + + const st = switch (self.stat()) { + .err => |err| return .{ .err = err }, + .result => |s| s, + }; + + const m = st.mode & posix.S.IFMT; + switch (m) { + posix.S.IFBLK => return .{ .result = .block_device }, + posix.S.IFCHR => return .{ .result = .character_device }, + posix.S.IFDIR => return .{ .result = .directory }, + posix.S.IFIFO => return .{ .result = .named_pipe }, + posix.S.IFLNK => return .{ .result = .sym_link }, + posix.S.IFREG => return .{ .result = .file }, + posix.S.IFSOCK => return .{ .result = .unix_domain_socket }, + else => { + return .{ .result = .file }; + }, + } +} + +pub const ReadToEndResult = struct { + bytes: std.ArrayList(u8) = std.ArrayList(u8).init(default_allocator), + err: ?Error = null, + + pub fn unwrap(self: *const ReadToEndResult) ![]u8 { + if (self.err) |err| { + try (bun.sys.Maybe(void){ .err = err }).unwrap(); + } + return self.bytes.items; + } +}; + +pub fn readFillBuf(this: File, buf: []u8) Maybe([]u8) { + var read_amount: usize = 0; + while (read_amount < buf.len) { + switch (if (comptime Environment.isPosix) + pread(this.handle, buf[read_amount..], @intCast(read_amount)) + else + sys.read(this.handle, buf[read_amount..])) { + .err => |err| { + return .{ .err = err }; + }, + .result => |bytes_read| { + if (bytes_read == 0) { + break; + } + + read_amount += bytes_read; + }, + } + } + + return .{ .result = buf[0..read_amount] }; +} + +pub fn readToEndWithArrayList(this: File, list: *std.ArrayList(u8), probably_small: bool) Maybe(usize) { + if (probably_small) { + list.ensureUnusedCapacity(64) catch bun.outOfMemory(); + } else { + list.ensureTotalCapacityPrecise( + switch (this.getEndPos()) { + .err => |err| { + return .{ .err = err }; + }, + .result => |s| s, + } + 16, + ) catch bun.outOfMemory(); + } + + var total: i64 = 0; + while (true) { + if (list.unusedCapacitySlice().len == 0) { + list.ensureUnusedCapacity(16) catch bun.outOfMemory(); + } + + switch (if (comptime Environment.isPosix) + pread(this.handle, list.unusedCapacitySlice(), total) + else + sys.read(this.handle, list.unusedCapacitySlice())) { + .err => |err| { + return .{ .err = err }; + }, + .result => |bytes_read| { + if (bytes_read == 0) { + break; + } + + list.items.len += bytes_read; + total += @intCast(bytes_read); + }, + } + } + + return .{ .result = @intCast(total) }; +} + +/// Use this function on potentially large files. +/// Calls fstat() on the file to get the size of the file and avoids reallocations + extra read() calls. +pub fn readToEnd(this: File, allocator: std.mem.Allocator) ReadToEndResult { + var list = std.ArrayList(u8).init(allocator); + return switch (readToEndWithArrayList(this, &list, false)) { + .err => |err| .{ .err = err, .bytes = list }, + .result => .{ .err = null, .bytes = list }, + }; +} + +/// Use this function on small files <= 1024 bytes. +/// File will skip the fstat() call, preallocating 64 bytes instead of the file's size. +pub fn readToEndSmall(this: File, allocator: std.mem.Allocator) ReadToEndResult { + var list = std.ArrayList(u8).init(allocator); + return switch (readToEndWithArrayList(this, &list, true)) { + .err => |err| .{ .err = err, .bytes = list }, + .result => .{ .err = null, .bytes = list }, + }; +} + +pub fn getPath(this: File, out_buffer: *bun.PathBuffer) Maybe([]u8) { + return getFdPath(this.handle, out_buffer); +} + +/// 1. Normalize the file path +/// 2. Open a file for reading +/// 2. Read the file to a buffer +/// 3. Return the File handle and the buffer +pub fn readFromUserInput(dir_fd: anytype, input_path: anytype, allocator: std.mem.Allocator) Maybe([]u8) { + var buf: bun.PathBuffer = undefined; + const normalized = bun.path.joinAbsStringBufZ( + bun.fs.FileSystem.instance.top_level_dir, + &buf, + &.{input_path}, + .loose, + ); + return readFrom(dir_fd, normalized, allocator); +} + +/// 1. Open a file for reading +/// 2. Read the file to a buffer +/// 3. Return the File handle and the buffer +pub fn readFileFrom(dir_fd: anytype, path: anytype, allocator: std.mem.Allocator) Maybe(struct { File, []u8 }) { + const ElementType = std.meta.Elem(@TypeOf(path)); + + const rc = brk: { + if (comptime Environment.isWindows and ElementType == u16) { + break :brk openatWindowsTMaybeNormalize(u16, from(dir_fd).handle, path, O.RDONLY, false); + } + + if (comptime ElementType == u8 and std.meta.sentinel(@TypeOf(path)) == null) { + break :brk sys.openatA(from(dir_fd).handle, path, O.RDONLY, 0); + } + + break :brk sys.openat(from(dir_fd).handle, path, O.RDONLY, 0); + }; + + const this = switch (rc) { + .err => |err| return .{ .err = err }, + .result => |fd| from(fd), + }; + + var result = this.readToEnd(allocator); + + if (result.err) |err| { + this.close(); + result.bytes.deinit(); + return .{ .err = err }; + } + + if (result.bytes.items.len == 0) { + // Don't allocate an empty string. + // We won't be modifying an empty slice, anyway. + return .{ .result = .{ this, @ptrCast(@constCast("")) } }; + } + + return .{ .result = .{ this, result.bytes.items } }; +} + +/// 1. Open a file for reading relative to a directory +/// 2. Read the file to a buffer +/// 3. Close the file +/// 4. Return the buffer +pub fn readFrom(dir_fd: anytype, path: anytype, allocator: std.mem.Allocator) Maybe([]u8) { + const file, const bytes = switch (readFileFrom(dir_fd, path, allocator)) { + .err => |err| return .{ .err = err }, + .result => |result| result, + }; + + file.close(); + return .{ .result = bytes }; +} + +const ToSourceOptions = struct { + convert_bom: bool = false, +}; + +pub fn toSourceAt(dir_fd: anytype, path: anytype, allocator: std.mem.Allocator, opts: ToSourceOptions) Maybe(bun.logger.Source) { + var bytes = switch (readFrom(dir_fd, path, allocator)) { + .err => |err| return .{ .err = err }, + .result => |bytes| bytes, + }; + + if (opts.convert_bom) { + if (bun.strings.BOM.detect(bytes)) |bom| { + bytes = bom.removeAndConvertToUTF8AndFree(allocator, bytes) catch bun.outOfMemory(); + } + } + + return .{ .result = bun.logger.Source.initPathString(path, bytes) }; +} + +pub fn toSource(path: anytype, allocator: std.mem.Allocator, opts: ToSourceOptions) Maybe(bun.logger.Source) { + return toSourceAt(std.fs.cwd(), path, allocator, opts); +} + +const bun = @import("bun"); +const Environment = bun.Environment; +const default_allocator = bun.default_allocator; +const windows = bun.windows; + +const sys = bun.sys; +const Error = bun.sys.Error; +const Maybe = bun.sys.Maybe; +const O = sys.O; +const SystemErrno = bun.sys.SystemErrno; +const fstat = sys.fstat; +const getFdPath = sys.getFdPath; +const getFileSize = sys.getFileSize; +const openatWindowsTMaybeNormalize = sys.openatWindowsTMaybeNormalize; +const pread = sys.pread; + +const std = @import("std"); +const posix = std.posix; diff --git a/src/sys/coreutils_error_map.zig b/src/sys/coreutils_error_map.zig new file mode 100644 index 0000000000..78d838d262 --- /dev/null +++ b/src/sys/coreutils_error_map.zig @@ -0,0 +1,270 @@ +/// This map is derived off of what coreutils uses in printing errors. This is +/// equivalent to `strerror`, but as strings with constant lifetime. +pub const coreutils_error_map = brk: { + // macOS and Linux have slightly different error messages. + const entries: []const struct { [:0]const u8, [:0]const u8 } = switch (Environment.os) { + // Since windows is just an emulation of linux, it will derive the linux error messages. + .linux, .windows, .wasm => &.{ + .{ "EPERM", "Operation not permitted" }, + .{ "ENOENT", "No such file or directory" }, + .{ "ESRCH", "No such process" }, + .{ "EINTR", "Interrupted system call" }, + .{ "EIO", "Input/output error" }, + .{ "ENXIO", "No such device or address" }, + .{ "E2BIG", "Argument list too long" }, + .{ "ENOEXEC", "Exec format error" }, + .{ "EBADF", "Bad file descriptor" }, + .{ "ECHILD", "No child processes" }, + .{ "EAGAIN", "Resource temporarily unavailable" }, + .{ "ENOMEM", "Cannot allocate memory" }, + .{ "EACCES", "Permission denied" }, + .{ "EFAULT", "Bad address" }, + .{ "ENOTBLK", "Block device required" }, + .{ "EBUSY", "Device or resource busy" }, + .{ "EEXIST", "File exists" }, + .{ "EXDEV", "Invalid cross-device link" }, + .{ "ENODEV", "No such device" }, + .{ "ENOTDIR", "Not a directory" }, + .{ "EISDIR", "Is a directory" }, + .{ "EINVAL", "Invalid argument" }, + .{ "ENFILE", "Too many open files in system" }, + .{ "EMFILE", "Too many open files" }, + .{ "ENOTTY", "Inappropriate ioctl for device" }, + .{ "ETXTBSY", "Text file busy" }, + .{ "EFBIG", "File too large" }, + .{ "ENOSPC", "No space left on device" }, + .{ "ESPIPE", "Illegal seek" }, + .{ "EROFS", "Read-only file system" }, + .{ "EMLINK", "Too many links" }, + .{ "EPIPE", "Broken pipe" }, + .{ "EDOM", "Numerical argument out of domain" }, + .{ "ERANGE", "Numerical result out of range" }, + .{ "EDEADLK", "Resource deadlock avoided" }, + .{ "ENAMETOOLONG", "File name too long" }, + .{ "ENOLCK", "No locks available" }, + .{ "ENOSYS", "Function not implemented" }, + .{ "ENOTEMPTY", "Directory not empty" }, + .{ "ELOOP", "Too many levels of symbolic links" }, + .{ "ENOMSG", "No message of desired type" }, + .{ "EIDRM", "Identifier removed" }, + .{ "ECHRNG", "Channel number out of range" }, + .{ "EL2NSYNC", "Level 2 not synchronized" }, + .{ "EL3HLT", "Level 3 halted" }, + .{ "EL3RST", "Level 3 reset" }, + .{ "ELNRNG", "Link number out of range" }, + .{ "EUNATCH", "Protocol driver not attached" }, + .{ "ENOCSI", "No CSI structure available" }, + .{ "EL2HLT", "Level 2 halted" }, + .{ "EBADE", "Invalid exchange" }, + .{ "EBADR", "Invalid request descriptor" }, + .{ "EXFULL", "Exchange full" }, + .{ "ENOANO", "No anode" }, + .{ "EBADRQC", "Invalid request code" }, + .{ "EBADSLT", "Invalid slot" }, + .{ "EBFONT", "Bad font file format" }, + .{ "ENOSTR", "Device not a stream" }, + .{ "ENODATA", "No data available" }, + .{ "ETIME", "Timer expired" }, + .{ "ENOSR", "Out of streams resources" }, + .{ "ENONET", "Machine is not on the network" }, + .{ "ENOPKG", "Package not installed" }, + .{ "EREMOTE", "Object is remote" }, + .{ "ENOLINK", "Link has been severed" }, + .{ "EADV", "Advertise error" }, + .{ "ESRMNT", "Srmount error" }, + .{ "ECOMM", "Communication error on send" }, + .{ "EPROTO", "Protocol error" }, + .{ "EMULTIHOP", "Multihop attempted" }, + .{ "EDOTDOT", "RFS specific error" }, + .{ "EBADMSG", "Bad message" }, + .{ "EOVERFLOW", "Value too large for defined data type" }, + .{ "ENOTUNIQ", "Name not unique on network" }, + .{ "EBADFD", "File descriptor in bad state" }, + .{ "EREMCHG", "Remote address changed" }, + .{ "ELIBACC", "Can not access a needed shared library" }, + .{ "ELIBBAD", "Accessing a corrupted shared library" }, + .{ "ELIBSCN", ".lib section in a.out corrupted" }, + .{ "ELIBMAX", "Attempting to link in too many shared libraries" }, + .{ "ELIBEXEC", "Cannot exec a shared library directly" }, + .{ "EILSEQ", "Invalid or incomplete multibyte or wide character" }, + .{ "ERESTART", "Interrupted system call should be restarted" }, + .{ "ESTRPIPE", "Streams pipe error" }, + .{ "EUSERS", "Too many users" }, + .{ "ENOTSOCK", "Socket operation on non-socket" }, + .{ "EDESTADDRREQ", "Destination address required" }, + .{ "EMSGSIZE", "Message too long" }, + .{ "EPROTOTYPE", "Protocol wrong type for socket" }, + .{ "ENOPROTOOPT", "Protocol not available" }, + .{ "EPROTONOSUPPORT", "Protocol not supported" }, + .{ "ESOCKTNOSUPPORT", "Socket type not supported" }, + .{ "EOPNOTSUPP", "Operation not supported" }, + .{ "EPFNOSUPPORT", "Protocol family not supported" }, + .{ "EAFNOSUPPORT", "Address family not supported by protocol" }, + .{ "EADDRINUSE", "Address already in use" }, + .{ "EADDRNOTAVAIL", "Cannot assign requested address" }, + .{ "ENETDOWN", "Network is down" }, + .{ "ENETUNREACH", "Network is unreachable" }, + .{ "ENETRESET", "Network dropped connection on reset" }, + .{ "ECONNABORTED", "Software caused connection abort" }, + .{ "ECONNRESET", "Connection reset by peer" }, + .{ "ENOBUFS", "No buffer space available" }, + .{ "EISCONN", "Transport endpoint is already connected" }, + .{ "ENOTCONN", "Transport endpoint is not connected" }, + .{ "ESHUTDOWN", "Cannot send after transport endpoint shutdown" }, + .{ "ETOOMANYREFS", "Too many references: cannot splice" }, + .{ "ETIMEDOUT", "Connection timed out" }, + .{ "ECONNREFUSED", "Connection refused" }, + .{ "EHOSTDOWN", "Host is down" }, + .{ "EHOSTUNREACH", "No route to host" }, + .{ "EALREADY", "Operation already in progress" }, + .{ "EINPROGRESS", "Operation now in progress" }, + .{ "ESTALE", "Stale file handle" }, + .{ "EUCLEAN", "Structure needs cleaning" }, + .{ "ENOTNAM", "Not a XENIX named type file" }, + .{ "ENAVAIL", "No XENIX semaphores available" }, + .{ "EISNAM", "Is a named type file" }, + .{ "EREMOTEIO", "Remote I/O error" }, + .{ "EDQUOT", "Disk quota exceeded" }, + .{ "ENOMEDIUM", "No medium found" }, + .{ "EMEDIUMTYPE", "Wrong medium type" }, + .{ "ECANCELED", "Operation canceled" }, + .{ "ENOKEY", "Required key not available" }, + .{ "EKEYEXPIRED", "Key has expired" }, + .{ "EKEYREVOKED", "Key has been revoked" }, + .{ "EKEYREJECTED", "Key was rejected by service" }, + .{ "EOWNERDEAD", "Owner died" }, + .{ "ENOTRECOVERABLE", "State not recoverable" }, + .{ "ERFKILL", "Operation not possible due to RF-kill" }, + .{ "EHWPOISON", "Memory page has hardware error" }, + }, + // Mac has slightly different messages. To keep it consistent with bash/coreutils, + // it will use those altered messages. + .mac => &.{ + .{ "E2BIG", "Argument list too long" }, + .{ "EACCES", "Permission denied" }, + .{ "EADDRINUSE", "Address already in use" }, + .{ "EADDRNOTAVAIL", "Can't assign requested address" }, + .{ "EAFNOSUPPORT", "Address family not supported by protocol family" }, + .{ "EAGAIN", "non-blocking and interrupt i/o. Resource temporarily unavailable" }, + .{ "EALREADY", "Operation already in progress" }, + .{ "EAUTH", "Authentication error" }, + .{ "EBADARCH", "Bad CPU type in executable" }, + .{ "EBADEXEC", "Program loading errors. Bad executable" }, + .{ "EBADF", "Bad file descriptor" }, + .{ "EBADMACHO", "Malformed Macho file" }, + .{ "EBADMSG", "Bad message" }, + .{ "EBADRPC", "RPC struct is bad" }, + .{ "EBUSY", "Device / Resource busy" }, + .{ "ECANCELED", "Operation canceled" }, + .{ "ECHILD", "No child processes" }, + .{ "ECONNABORTED", "Software caused connection abort" }, + .{ "ECONNREFUSED", "Connection refused" }, + .{ "ECONNRESET", "Connection reset by peer" }, + .{ "EDEADLK", "Resource deadlock avoided" }, + .{ "EDESTADDRREQ", "Destination address required" }, + .{ "EDEVERR", "Device error, for example paper out" }, + .{ "EDOM", "math software. Numerical argument out of domain" }, + .{ "EDQUOT", "Disc quota exceeded" }, + .{ "EEXIST", "File or folder exists" }, + .{ "EFAULT", "Bad address" }, + .{ "EFBIG", "File too large" }, + .{ "EFTYPE", "Inappropriate file type or format" }, + .{ "EHOSTDOWN", "Host is down" }, + .{ "EHOSTUNREACH", "No route to host" }, + .{ "EIDRM", "Identifier removed" }, + .{ "EILSEQ", "Illegal byte sequence" }, + .{ "EINPROGRESS", "Operation now in progress" }, + .{ "EINTR", "Interrupted system call" }, + .{ "EINVAL", "Invalid argument" }, + .{ "EIO", "Input/output error" }, + .{ "EISCONN", "Socket is already connected" }, + .{ "EISDIR", "Is a directory" }, + .{ "ELOOP", "Too many levels of symbolic links" }, + .{ "EMFILE", "Too many open files" }, + .{ "EMLINK", "Too many links" }, + .{ "EMSGSIZE", "Message too long" }, + .{ "EMULTIHOP", "Reserved" }, + .{ "ENAMETOOLONG", "File name too long" }, + .{ "ENEEDAUTH", "Need authenticator" }, + .{ "ENETDOWN", "ipc/network software - operational errors Network is down" }, + .{ "ENETRESET", "Network dropped connection on reset" }, + .{ "ENETUNREACH", "Network is unreachable" }, + .{ "ENFILE", "Too many open files in system" }, + .{ "ENOATTR", "Attribute not found" }, + .{ "ENOBUFS", "No buffer space available" }, + .{ "ENODATA", "No message available on STREAM" }, + .{ "ENODEV", "Operation not supported by device" }, + .{ "ENOENT", "No such file or directory" }, + .{ "ENOEXEC", "Exec format error" }, + .{ "ENOLCK", "No locks available" }, + .{ "ENOLINK", "Reserved" }, + .{ "ENOMEM", "Out of memory" }, + .{ "ENOMSG", "No message of desired type" }, + .{ "ENOPOLICY", "No such policy registered" }, + .{ "ENOPROTOOPT", "Protocol not available" }, + .{ "ENOSPC", "No space left on device" }, + .{ "ENOSR", "No STREAM resources" }, + .{ "ENOSTR", "Not a STREAM" }, + .{ "ENOSYS", "Function not implemented" }, + .{ "ENOTBLK", "Block device required" }, + .{ "ENOTCONN", "Socket is not connected" }, + .{ "ENOTDIR", "Not a directory" }, + .{ "ENOTEMPTY", "Directory not empty" }, + .{ "ENOTRECOVERABLE", "State not recoverable" }, + .{ "ENOTSOCK", "ipc/network software - argument errors. Socket operation on non-socket" }, + .{ "ENOTSUP", "Operation not supported" }, + .{ "ENOTTY", "Inappropriate ioctl for device" }, + .{ "ENXIO", "Device not configured" }, + .{ "EOVERFLOW", "Value too large to be stored in data type" }, + .{ "EOWNERDEAD", "Previous owner died" }, + .{ "EPERM", "Operation not permitted" }, + .{ "EPFNOSUPPORT", "Protocol family not supported" }, + .{ "EPIPE", "Broken pipe" }, + .{ "EPROCLIM", "quotas & mush. Too many processes" }, + .{ "EPROCUNAVAIL", "Bad procedure for program" }, + .{ "EPROGMISMATCH", "Program version wrong" }, + .{ "EPROGUNAVAIL", "RPC prog. not avail" }, + .{ "EPROTO", "Protocol error" }, + .{ "EPROTONOSUPPORT", "Protocol not supported" }, + .{ "EPROTOTYPE", "Protocol wrong type for socket" }, + .{ "EPWROFF", "Intelligent device errors. Device power is off" }, + .{ "EQFULL", "Interface output queue is full" }, + .{ "ERANGE", "Result too large" }, + .{ "EREMOTE", "Too many levels of remote in path" }, + .{ "EROFS", "Read-only file system" }, + .{ "ERPCMISMATCH", "RPC version wrong" }, + .{ "ESHLIBVERS", "Shared library version mismatch" }, + .{ "ESHUTDOWN", "Can't send after socket shutdown" }, + .{ "ESOCKTNOSUPPORT", "Socket type not supported" }, + .{ "ESPIPE", "Illegal seek" }, + .{ "ESRCH", "No such process" }, + .{ "ESTALE", "Network File System. Stale NFS file handle" }, + .{ "ETIME", "STREAM ioctl timeout" }, + .{ "ETIMEDOUT", "Operation timed out" }, + .{ "ETOOMANYREFS", "Too many references: can't splice" }, + .{ "ETXTBSY", "Text file busy" }, + .{ "EUSERS", "Too many users" }, + .{ "EWOULDBLOCK", "Operation would block" }, + .{ "EXDEV", "Cross-device link" }, + }, + }; + + var map = std.EnumMap(SystemErrno, [:0]const u8).initFull("unknown error"); + for (entries) |entry| { + const key, const text = entry; + if (@hasField(SystemErrno, key)) { + map.put(@field(SystemErrno, key), text); + } + } + + // sanity check + bun.assert(std.mem.eql(u8, map.get(SystemErrno.ENOENT).?, "No such file or directory")); + + break :brk map; +}; + +const std = @import("std"); + +const bun = @import("bun"); +const Environment = bun.Environment; +const SystemErrno = bun.sys.SystemErrno; diff --git a/src/sys/libuv_error_map.zig b/src/sys/libuv_error_map.zig new file mode 100644 index 0000000000..340dafb988 --- /dev/null +++ b/src/sys/libuv_error_map.zig @@ -0,0 +1,105 @@ +/// This map is derived off of uv.h's definitions, and is what Node.js uses in printing errors. +pub const libuv_error_map = brk: { + const entries: []const struct { [:0]const u8, [:0]const u8 } = &.{ + .{ "E2BIG", "argument list too long" }, + .{ "EACCES", "permission denied" }, + .{ "EADDRINUSE", "address already in use" }, + .{ "EADDRNOTAVAIL", "address not available" }, + .{ "EAFNOSUPPORT", "address family not supported" }, + .{ "EAGAIN", "resource temporarily unavailable" }, + .{ "EAI_ADDRFAMILY", "address family not supported" }, + .{ "EAI_AGAIN", "temporary failure" }, + .{ "EAI_BADFLAGS", "bad ai_flags value" }, + .{ "EAI_BADHINTS", "invalid value for hints" }, + .{ "EAI_CANCELED", "request canceled" }, + .{ "EAI_FAIL", "permanent failure" }, + .{ "EAI_FAMILY", "ai_family not supported" }, + .{ "EAI_MEMORY", "out of memory" }, + .{ "EAI_NODATA", "no address" }, + .{ "EAI_NONAME", "unknown node or service" }, + .{ "EAI_OVERFLOW", "argument buffer overflow" }, + .{ "EAI_PROTOCOL", "resolved protocol is unknown" }, + .{ "EAI_SERVICE", "service not available for socket type" }, + .{ "EAI_SOCKTYPE", "socket type not supported" }, + .{ "EALREADY", "connection already in progress" }, + .{ "EBADF", "bad file descriptor" }, + .{ "EBUSY", "resource busy or locked" }, + .{ "ECANCELED", "operation canceled" }, + .{ "ECHARSET", "invalid Unicode character" }, + .{ "ECONNABORTED", "software caused connection abort" }, + .{ "ECONNREFUSED", "connection refused" }, + .{ "ECONNRESET", "connection reset by peer" }, + .{ "EDESTADDRREQ", "destination address required" }, + .{ "EEXIST", "file already exists" }, + .{ "EFAULT", "bad address in system call argument" }, + .{ "EFBIG", "file too large" }, + .{ "EHOSTUNREACH", "host is unreachable" }, + .{ "EINTR", "interrupted system call" }, + .{ "EINVAL", "invalid argument" }, + .{ "EIO", "i/o error" }, + .{ "EISCONN", "socket is already connected" }, + .{ "EISDIR", "illegal operation on a directory" }, + .{ "ELOOP", "too many symbolic links encountered" }, + .{ "EMFILE", "too many open files" }, + .{ "EMSGSIZE", "message too long" }, + .{ "ENAMETOOLONG", "name too long" }, + .{ "ENETDOWN", "network is down" }, + .{ "ENETUNREACH", "network is unreachable" }, + .{ "ENFILE", "file table overflow" }, + .{ "ENOBUFS", "no buffer space available" }, + .{ "ENODEV", "no such device" }, + .{ "ENOENT", "no such file or directory" }, + .{ "ENOMEM", "not enough memory" }, + .{ "ENONET", "machine is not on the network" }, + .{ "ENOPROTOOPT", "protocol not available" }, + .{ "ENOSPC", "no space left on device" }, + .{ "ENOSYS", "function not implemented" }, + .{ "ENOTCONN", "socket is not connected" }, + .{ "ENOTDIR", "not a directory" }, + .{ "ENOTEMPTY", "directory not empty" }, + .{ "ENOTSOCK", "socket operation on non-socket" }, + .{ "ENOTSUP", "operation not supported on socket" }, + .{ "EOVERFLOW", "value too large for defined data type" }, + .{ "EPERM", "operation not permitted" }, + .{ "EPIPE", "broken pipe" }, + .{ "EPROTO", "protocol error" }, + .{ "EPROTONOSUPPORT", "protocol not supported" }, + .{ "EPROTOTYPE", "protocol wrong type for socket" }, + .{ "ERANGE", "result too large" }, + .{ "EROFS", "read-only file system" }, + .{ "ESHUTDOWN", "cannot send after transport endpoint shutdown" }, + .{ "ESPIPE", "invalid seek" }, + .{ "ESRCH", "no such process" }, + .{ "ETIMEDOUT", "connection timed out" }, + .{ "ETXTBSY", "text file is busy" }, + .{ "EXDEV", "cross-device link not permitted" }, + .{ "UNKNOWN", "unknown error" }, + .{ "EOF", "end of file" }, + .{ "ENXIO", "no such device or address" }, + .{ "EMLINK", "too many links" }, + .{ "EHOSTDOWN", "host is down" }, + .{ "EREMOTEIO", "remote I/O error" }, + .{ "ENOTTY", "inappropriate ioctl for device" }, + .{ "EFTYPE", "inappropriate file type or format" }, + .{ "EILSEQ", "illegal byte sequence" }, + .{ "ESOCKTNOSUPPORT", "socket type not supported" }, + .{ "ENODATA", "no data available" }, + .{ "EUNATCH", "protocol driver not attached" }, + }; + var map = std.EnumMap(SystemErrno, [:0]const u8).initFull("unknown error"); + for (entries) |entry| { + const key, const text = entry; + if (@hasField(SystemErrno, key)) { + map.put(@field(SystemErrno, key), text); + } + } + + // sanity check + bun.assert(std.mem.eql(u8, map.get(SystemErrno.ENOENT).?, "no such file or directory")); + + break :brk map; +}; + +const bun = @import("bun"); +const std = @import("std"); +const SystemErrno = bun.sys.SystemErrno; diff --git a/src/threading.zig b/src/threading.zig index 4cb214e590..504e6af054 100644 --- a/src/threading.zig +++ b/src/threading.zig @@ -2,6 +2,7 @@ pub const Mutex = @import("./threading/Mutex.zig"); pub const Futex = @import("./threading/Futex.zig"); pub const Condition = @import("./threading/Condition.zig"); pub const GuardedValue = @import("./threading/guarded_value.zig").GuardedValue; +pub const DebugGuardedValue = @import("./threading/guarded_value.zig").DebugGuardedValue; pub const WaitGroup = @import("./threading/WaitGroup.zig"); pub const ThreadPool = @import("./threading/ThreadPool.zig"); pub const Channel = @import("./threading/channel.zig").Channel; diff --git a/src/threading/ThreadPool.zig b/src/threading/ThreadPool.zig index 610d7440b7..5862ccb281 100644 --- a/src/threading/ThreadPool.zig +++ b/src/threading/ThreadPool.zig @@ -550,6 +550,8 @@ pub const Thread = struct { /// Thread entry point which runs a worker for the ThreadPool fn run(thread_pool: *ThreadPool) void { + bun.mimalloc.mi_thread_set_in_threadpool(); + { var counter_buf: [100]u8 = undefined; const int = counter.fetchAdd(1, .seq_cst); diff --git a/src/threading/guarded_value.zig b/src/threading/guarded_value.zig index 8124051f5d..ba5640988e 100644 --- a/src/threading/guarded_value.zig +++ b/src/threading/guarded_value.zig @@ -6,10 +6,10 @@ pub fn GuardedValue(comptime Value: type, comptime Mutex: type) type { /// The raw value. Don't use this if there might be concurrent accesses. unsynchronized_value: Value, - mutex: Mutex = .{}, + mutex: Mutex, - pub fn init(value: Value) Self { - return .{ .unsynchronized_value = value }; + pub fn init(value: Value, mutex: Mutex) Self { + return .{ .unsynchronized_value = value, .mutex = mutex }; } /// Lock the mutex and return a pointer to the value. Remember to call `unlock`! @@ -24,3 +24,9 @@ pub fn GuardedValue(comptime Value: type, comptime Mutex: type) type { } }; } + +pub fn DebugGuardedValue(comptime Value: type) type { + return GuardedValue(Value, bun.DebugThreadLock); +} + +const bun = @import("bun"); diff --git a/src/watcher/INotifyWatcher.zig b/src/watcher/INotifyWatcher.zig index 8781b37e95..65b634c566 100644 --- a/src/watcher/INotifyWatcher.zig +++ b/src/watcher/INotifyWatcher.zig @@ -199,7 +199,7 @@ pub fn read(this: *INotifyWatcher) bun.sys.Maybe([]const *align(1) Event) { event.watch_descriptor, event.cookie, event.mask, - bun.fmt.quote(event.name()), + bun.fmt.quote(if (event.name_len > 0) event.name() else ""), }); // when under high load with short file paths, it is very easy to @@ -229,76 +229,130 @@ pub fn stop(this: *INotifyWatcher) void { pub fn watchLoopCycle(this: *bun.Watcher) bun.sys.Maybe(void) { defer Output.flush(); - var events = switch (this.platform.read()) { + const events = switch (this.platform.read()) { .result => |result| result, .err => |err| return .{ .err = err }, }; if (events.len == 0) return .success; - // TODO: is this thread safe? - var remaining_events = events.len; - const eventlist_index = this.watchlist.items(.eventlist_index); - while (remaining_events > 0) { + var event_id: usize = 0; + var events_processed: usize = 0; + + while (events_processed < events.len) { var name_off: u8 = 0; var temp_name_list: [128]?[:0]u8 = undefined; var temp_name_off: u8 = 0; - const slice = events[0..@min(128, remaining_events, this.watch_events.len)]; - var watchevents = this.watch_events[0..slice.len]; - var watch_event_id: u32 = 0; - for (slice) |event| { - watchevents[watch_event_id] = watchEventFromInotifyEvent( + // Process events one by one, batching when we hit limits + while (events_processed < events.len) { + const event = events[events_processed]; + + // Check if we're about to exceed the watch_events array capacity + if (event_id >= this.watch_events.len) { + // Process current batch of events + switch (processINotifyEventBatch(this, event_id, temp_name_list[0..temp_name_off])) { + .err => |err| return .{ .err = err }, + .result => {}, + } + // Reset event_id to start a new batch + event_id = 0; + name_off = 0; + temp_name_off = 0; + } + + // Check if we can fit this event's name in temp_name_list + const will_have_name = event.name_len > 0; + if (will_have_name and temp_name_off >= temp_name_list.len) { + // Process current batch and start a new one + if (event_id > 0) { + switch (processINotifyEventBatch(this, event_id, temp_name_list[0..temp_name_off])) { + .err => |err| return .{ .err = err }, + .result => {}, + } + event_id = 0; + name_off = 0; + temp_name_off = 0; + } + } + + this.watch_events[event_id] = watchEventFromInotifyEvent( event, @intCast(std.mem.indexOfScalar( EventListIndex, eventlist_index, event.watch_descriptor, - ) orelse continue), + ) orelse { + events_processed += 1; + continue; + }), ); - temp_name_list[temp_name_off] = if (event.name_len > 0) - event.name() - else - null; - watchevents[watch_event_id].name_off = temp_name_off; - watchevents[watch_event_id].name_len = @as(u8, @intFromBool((event.name_len > 0))); - temp_name_off += @as(u8, @intFromBool((event.name_len > 0))); - watch_event_id += 1; + // Safely handle event names with bounds checking + if (event.name_len > 0 and temp_name_off < temp_name_list.len) { + temp_name_list[temp_name_off] = event.name(); + this.watch_events[event_id].name_off = temp_name_off; + this.watch_events[event_id].name_len = 1; + temp_name_off += 1; + } else { + this.watch_events[event_id].name_off = temp_name_off; + this.watch_events[event_id].name_len = 0; + } + + event_id += 1; + events_processed += 1; } - var all_events = watchevents[0..watch_event_id]; - std.sort.pdq(WatchEvent, all_events, {}, WatchEvent.sortByIndex); + // Process any remaining events in the final batch + if (event_id > 0) { + switch (processINotifyEventBatch(this, event_id, temp_name_list[0..temp_name_off])) { + .err => |err| return .{ .err = err }, + .result => {}, + } + } + break; + } - var last_event_index: usize = 0; - var last_event_id: EventListIndex = std.math.maxInt(EventListIndex); + return .success; +} - for (all_events, 0..) |_, i| { - if (all_events[i].name_len > 0) { +fn processINotifyEventBatch(this: *bun.Watcher, event_count: usize, temp_name_list: []?[:0]u8) bun.sys.Maybe(void) { + if (event_count == 0) { + return .success; + } + + var name_off: u8 = 0; + var all_events = this.watch_events[0..event_count]; + std.sort.pdq(WatchEvent, all_events, {}, WatchEvent.sortByIndex); + + var last_event_index: usize = 0; + var last_event_id: EventListIndex = std.math.maxInt(EventListIndex); + + for (all_events, 0..) |_, i| { + if (all_events[i].name_len > 0) { + // Check bounds before accessing arrays + if (name_off < this.changed_filepaths.len and all_events[i].name_off < temp_name_list.len) { this.changed_filepaths[name_off] = temp_name_list[all_events[i].name_off]; all_events[i].name_off = name_off; name_off += 1; } - - if (all_events[i].index == last_event_id) { - all_events[last_event_index].merge(all_events[i]); - continue; - } - last_event_index = i; - last_event_id = all_events[i].index; } - if (all_events.len == 0) return .success; - this.mutex.lock(); - defer this.mutex.unlock(); - if (this.running) { - // all_events.len == 0 is checked above, so last_event_index + 1 is safe - this.onFileUpdate(this.ctx, all_events[0 .. last_event_index + 1], this.changed_filepaths[0..name_off], this.watchlist); - } else { - break; + if (all_events[i].index == last_event_id) { + all_events[last_event_index].merge(all_events[i]); + continue; } - remaining_events -= slice.len; + last_event_index = i; + last_event_id = all_events[i].index; + } + if (all_events.len == 0) return .success; + + this.mutex.lock(); + defer this.mutex.unlock(); + if (this.running) { + // all_events.len == 0 is checked above, so last_event_index + 1 is safe + this.onFileUpdate(this.ctx, all_events[0 .. last_event_index + 1], this.changed_filepaths[0..name_off], this.watchlist); } return .success; diff --git a/src/watcher/WindowsWatcher.zig b/src/watcher/WindowsWatcher.zig index b387097662..5b2267f7ac 100644 --- a/src/watcher/WindowsWatcher.zig +++ b/src/watcher/WindowsWatcher.zig @@ -238,18 +238,43 @@ pub fn watchLoopCycle(this: *bun.Watcher) bun.sys.Maybe(void) { // skip unrelated items if (rel == .unrelated) continue; // if the event is for a parent dir of the item, only emit it if it's a delete or rename + + // Check if we're about to exceed the watch_events array capacity + if (event_id >= this.watch_events.len) { + // Process current batch of events + switch (processWatchEventBatch(this, event_id)) { + .err => |err| return .{ .err = err }, + .result => {}, + } + // Reset event_id to start a new batch + event_id = 0; + } + this.watch_events[event_id] = createWatchEvent(event, @truncate(item_idx)); event_id += 1; } } } - if (event_id == 0) { + + // Process any remaining events in the final batch + if (event_id > 0) { + switch (processWatchEventBatch(this, event_id)) { + .err => |err| return .{ .err = err }, + .result => {}, + } + } + + return .success; +} + +fn processWatchEventBatch(this: *bun.Watcher, event_count: usize) bun.sys.Maybe(void) { + if (event_count == 0) { return .success; } - // log("event_id: {d}\n", .{event_id}); + // log("event_count: {d}\n", .{event_count}); - var all_events = this.watch_events[0..event_id]; + var all_events = this.watch_events[0..event_count]; std.sort.pdq(WatchEvent, all_events, {}, WatchEvent.sortByIndex); var last_event_index: usize = 0; diff --git a/test/CLAUDE.md b/test/CLAUDE.md index e528fbaaba..f0f112ed62 100644 --- a/test/CLAUDE.md +++ b/test/CLAUDE.md @@ -81,6 +81,14 @@ await promise; If it's several callbacks, it's okay to use callbacks. We aren't a stickler for this. +### No timeouts + +**CRITICAL**: Do not set a timeout on tests. Bun already has timeouts. + +### Use port 0 to get a random port + +Most APIs in Bun support `port: 0` to get a random port. Never hardcode ports. Avoid using your own random port number function. + ### Creating temporary files Use `tempDirWithFiles` to create a temporary directory with files. diff --git a/test/bake/dev/ecosystem.test.ts b/test/bake/dev/ecosystem.test.ts index e93a39ff6d..0f2aece4fa 100644 --- a/test/bake/dev/ecosystem.test.ts +++ b/test/bake/dev/ecosystem.test.ts @@ -12,6 +12,7 @@ import { devTest } from "../bake-harness"; devTest("svelte component islands example", { fixture: "svelte-component-islands", timeoutMultiplier: 2, + skip: ["win32"], async test(dev) { const html = await dev.fetch("/").text(); if (html.includes("Bun__renderFallbackError")) throw new Error("failed"); diff --git a/test/bun.lock b/test/bun.lock index d42fcf7838..e058d005b5 100644 --- a/test/bun.lock +++ b/test/bun.lock @@ -47,6 +47,7 @@ "http2-wrapper": "2.2.1", "https-proxy-agent": "7.0.5", "iconv-lite": "0.6.3", + "immutable": "5.1.3", "isbot": "5.1.13", "jest-extended": "4.0.0", "jimp": "1.6.0", @@ -90,7 +91,7 @@ "tsyringe": "4.8.0", "type-graphql": "2.0.0-rc.2", "typeorm": "0.3.20", - "typescript": "5.8.3", + "typescript": "5.9.2", "undici": "5.20.0", "unzipper": "0.12.3", "uuid": "11.1.0", @@ -1515,7 +1516,7 @@ "image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="], - "immutable": ["immutable@4.3.7", "", {}, "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw=="], + "immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="], "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], @@ -2501,7 +2502,7 @@ "typeorm": ["typeorm@0.3.20", "", { "dependencies": { "@sqltools/formatter": "^1.2.5", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "chalk": "^4.1.2", "cli-highlight": "^2.1.11", "dayjs": "^1.11.9", "debug": "^4.3.4", "dotenv": "^16.0.3", "glob": "^10.3.10", "mkdirp": "^2.1.3", "reflect-metadata": "^0.2.1", "sha.js": "^2.4.11", "tslib": "^2.5.0", "uuid": "^9.0.0", "yargs": "^17.6.2" }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0", "@sap/hana-client": "^2.12.25", "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", "mongodb": "^5.8.0", "mssql": "^9.1.1 || ^10.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", "typeorm-aurora-data-api-driver": "^2.0.0" }, "optionalPeers": ["@google-cloud/spanner", "@sap/hana-client", "better-sqlite3", "hdb-pool", "ioredis", "mongodb", "mssql", "mysql2", "oracledb", "pg", "pg-native", "pg-query-stream", "redis", "sql.js", "sqlite3", "ts-node", "typeorm-aurora-data-api-driver"], "bin": { "typeorm": "cli.js", "typeorm-ts-node-esm": "cli-ts-node-esm.js", "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js" } }, "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q=="], - "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], @@ -3191,6 +3192,8 @@ "sass/chokidar": ["chokidar@4.0.1", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA=="], + "sass/immutable": ["immutable@4.3.7", "", {}, "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw=="], + "schema-utils/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], "send/debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], diff --git a/test/bundler/bundler_browser.test.ts b/test/bundler/bundler_browser.test.ts index 53829e84f5..36378d112a 100644 --- a/test/bundler/bundler_browser.test.ts +++ b/test/bundler/bundler_browser.test.ts @@ -41,6 +41,23 @@ describe("bundler", () => { "zlib": "polyfill", }; + itBundled("browser/NodeBuffer#21522", { + files: { + "/entry.js": /* js */ ` + import { Buffer } from "node:buffer"; + const x = Buffer.alloc(5); + x.write("68656c6c6f", "hex"); + console.log(x); + `, + }, + target: "browser", + run: { + stdout: "", + }, + onAfterBundle(api) { + api.expectFile("out.js").not.toInclude("import "); + }, + }); itBundled("browser/NodeBuffer#12272", { files: { "/entry.js": /* js */ ` diff --git a/test/cli/hot/watch-many-dirs.test.ts b/test/cli/hot/watch-many-dirs.test.ts new file mode 100644 index 0000000000..dad90166ad --- /dev/null +++ b/test/cli/hot/watch-many-dirs.test.ts @@ -0,0 +1,101 @@ +import { spawn } from "bun"; +import { describe, expect, test } from "bun:test"; +import { bunEnv, bunExe, forEachLine, isASAN, isCI, tempDirWithFiles } from "harness"; +import { mkdirSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; + +describe("--hot with many directories", () => { + // TODO: fix watcher thread exit handling so the main thread waits for the + // watcher thread to exit. This causes a crash inside the libc exit() function + // that triggers in ASAN. + test.skipIf(isCI && isASAN)( + "handles 129 directories being updated simultaneously", + async () => { + // Create initial test structure + const tmpdir = tempDirWithFiles("hot-many-dirs", { + "entry.js": `console.log('Initial load');`, + }); + + // Generate 129 directories with files + const dirCount = 129; + const maxCount = 3; + for (let i = 0; i < dirCount; i++) { + const dirName = `dir-${i.toString().padStart(4, "0")}`; + const dirPath = join(tmpdir, dirName); + mkdirSync(dirPath, { recursive: true }); + + // Create an index.js in each directory + writeFileSync(join(dirPath, "index.js"), `export const value${i} = ${i};`); + } + + // Create main index that imports all directories + const imports = Array.from({ length: dirCount }, (_, i) => { + const dirName = `dir-${i.toString().padStart(4, "0")}`; + return `import * as dir${i} from './${dirName}/index.js';`; + }).join("\n"); + + writeFileSync( + join(tmpdir, "entry.js"), + ` +${imports} +console.log('Loaded', ${dirCount}, 'directories'); +(globalThis.reloaded ??= 0); +if (globalThis.reloaded++ >= ${maxCount}) process.exit(0); +`, + ); + + // Start bun --hot + await using proc = spawn({ + cmd: [bunExe(), "--hot", "entry.js"], + cwd: tmpdir, + env: bunEnv, + stdout: "pipe", + stderr: "inherit", + }); + + const stdout = proc.stdout; + + const iter = forEachLine(stdout); + + // Wait for initial load + let { value: line } = await iter.next(); + expect(line).toContain(`Loaded ${dirCount} directories`); + + // Trigger maxCount reload cycles + let reloadCount = 0; + + for (let cycle = 0; cycle < maxCount; cycle++) { + // Update all files simultaneously + const timestamp = Date.now() + cycle; + const updatePromises = []; + + for (let i = 0; i < dirCount; i++) { + const dirName = `dir-${i.toString().padStart(4, "0")}`; + const filePath = join(tmpdir, dirName, "index.js"); + + updatePromises.push( + Bun.write(filePath, `export const value${i} = ${i};\nexport const timestamp${i} = ${timestamp};`), + ); + } + + // Wait for all updates to complete + await Promise.all(updatePromises); + + // Wait for reload message + ({ value: line } = await iter.next()); + expect(line).toContain(`Loaded ${dirCount} directories`); + reloadCount++; + } + + // Verify we got maxCount successful reloads + expect(reloadCount).toBe(maxCount); + + // Wait for the process to exit on its own after maxCount reloads + const exitCode = await proc.exited; + + // Should exit with 0 + expect(exitCode).toBe(0); + }, + 30000, + ); // 30 second timeout +}); diff --git a/test/cli/install/bun-install-registry.test.ts b/test/cli/install/bun-install-registry.test.ts index 0310cde1f2..05b9823d86 100644 --- a/test/cli/install/bun-install-registry.test.ts +++ b/test/cli/install/bun-install-registry.test.ts @@ -8484,6 +8484,81 @@ describe("outdated", () => { expect(out).toContain("no-deps"); expect(out).toContain("a-dep"); }); + + test("--recursive flag for outdated", async () => { + // First verify the flag appears in help + const { + stdout: helpOut, + stderr: helpErr, + exited: helpExited, + } = spawn({ + cmd: [bunExe(), "outdated", "--help"], + cwd: packageDir, + stdout: "pipe", + stderr: "pipe", + env, + }); + + const help = (await new Response(helpOut).text()) + (await new Response(helpErr).text()); + expect(await helpExited).toBe(0); + expect(help).toContain("--recursive"); + expect(help).toContain("-r"); + + // Setup workspace + await setupWorkspace(); + await runBunInstall(env, packageDir); + + // Test --recursive shows all workspaces + const out = await runBunOutdated(env, packageDir, "--recursive"); + expect(out).toContain("no-deps"); + expect(out).toContain("a-dep"); + expect(out).toContain("prereleases-1"); + }); + + test("catalog grouping with multiple workspaces", async () => { + await Promise.all([ + write( + packageJson, + JSON.stringify({ + name: "root", + workspaces: ["packages/*"], + catalog: { + "no-deps": "1.0.0", + }, + }), + ), + write( + join(packageDir, "packages", "workspace-a", "package.json"), + JSON.stringify({ + name: "workspace-a", + dependencies: { + "no-deps": "catalog:", + }, + }), + ), + write( + join(packageDir, "packages", "workspace-b", "package.json"), + JSON.stringify({ + name: "workspace-b", + dependencies: { + "no-deps": "catalog:", + }, + }), + ), + ]); + + await runBunInstall(env, packageDir); + + // Test with filter to show workspace column and grouping + const out = await runBunOutdated(env, packageDir, "--filter", "*"); + // Should show all workspaces with catalog entries + expect(out).toContain("workspace-a"); + expect(out).toContain("workspace-b"); + expect(out).toContain("no-deps"); + + // The catalog grouping should show which workspaces use it + expect(out).toMatch(/catalog.*workspace-a.*workspace-b|workspace-b.*workspace-a/); + }); }); // TODO: setup registry to run across multiple test files, then move this and a few other describe diff --git a/test/cli/install/bun-update.test.ts b/test/cli/install/bun-update.test.ts index 15a8bd28e8..9443557bb1 100644 --- a/test/cli/install/bun-update.test.ts +++ b/test/cli/install/bun-update.test.ts @@ -1,6 +1,6 @@ import { file, spawn } from "bun"; import { afterAll, afterEach, beforeAll, beforeEach, expect, it } from "bun:test"; -import { access, readFile, rm, writeFile } from "fs/promises"; +import { access, mkdir, readFile, rm, writeFile } from "fs/promises"; import { bunExe, bunEnv as env, readdirSorted, toBeValidBin, toHaveBins } from "harness"; import { join } from "path"; import { @@ -369,3 +369,113 @@ it("lockfile should not be modified when there are no version changes, issue#588 // Assert we actually made a request to the registry for each update expect(urls).toHaveLength(count); }); + +it("should support catalog versions in update", async () => { + const urls: string[] = []; + setHandler(dummyRegistry(urls)); + + // Create a monorepo with catalog + await writeFile( + join(package_dir, "package.json"), + JSON.stringify({ + name: "root", + catalog: { + "no-deps": "^1.0.0", + }, + workspaces: ["packages/*"], + }), + ); + + await mkdir(join(package_dir, "packages", "workspace-a"), { recursive: true }); + await writeFile( + join(package_dir, "packages", "workspace-a", "package.json"), + JSON.stringify({ + name: "workspace-a", + dependencies: { + "no-deps": "catalog:", + }, + }), + ); + + // Test that update works with catalog dependencies + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "update", "--dry-run"], + cwd: join(package_dir, "packages", "workspace-a"), + stdout: "pipe", + stderr: "pipe", + env, + }); + + const err = await new Response(stderr).text(); + const out = await new Response(stdout).text(); + + // Should not crash with catalog dependencies + expect(err).not.toContain("panic"); + expect(err).not.toContain("segfault"); + + // Verify catalog reference is preserved in package.json + const pkg = await file(join(package_dir, "packages", "workspace-a", "package.json")).json(); + expect(pkg.dependencies["no-deps"]).toBe("catalog:"); +}); + +it("should support --recursive flag", async () => { + // First verify the flag appears in help + const { + stdout: helpOut, + stderr: helpErr, + exited: helpExited, + } = spawn({ + cmd: [bunExe(), "update", "--help"], + cwd: package_dir, + stdout: "pipe", + stderr: "pipe", + env, + }); + + const help = (await new Response(helpOut).text()) + (await new Response(helpErr).text()); + expect(await helpExited).toBe(0); + expect(help).toContain("--recursive"); + expect(help).toContain("-r"); + + // Now test that --recursive actually works + await writeFile( + join(package_dir, "package.json"), + JSON.stringify({ + name: "root", + workspaces: ["packages/*"], + dependencies: { + "no-deps": "^1.0.0", + }, + }), + ); + + await mkdir(join(package_dir, "packages", "pkg1"), { recursive: true }); + await writeFile( + join(package_dir, "packages", "pkg1", "package.json"), + JSON.stringify({ + name: "pkg1", + dependencies: { + "no-deps": "^1.0.0", + }, + }), + ); + + // Test recursive update (might fail without lockfile, but shouldn't crash) + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "update", "--recursive", "--dry-run"], + cwd: package_dir, + stdout: "pipe", + stderr: "pipe", + env, + }); + + const out = await new Response(stdout).text(); + const err = await new Response(stderr).text(); + + // Should not crash + expect(err).not.toContain("panic"); + expect(err).not.toContain("segfault"); + + // Should recognize the flag (either process workspaces or show error about missing lockfile) + expect(out + err).toMatch(/bun update|missing lockfile|nothing to update/); +}); diff --git a/test/cli/install/isolated-install.test.ts b/test/cli/install/isolated-install.test.ts index 48308da2eb..4763b537f0 100644 --- a/test/cli/install/isolated-install.test.ts +++ b/test/cli/install/isolated-install.test.ts @@ -1,14 +1,13 @@ import { file, spawn, write } from "bun"; -import { afterAll, beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test"; +import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { existsSync, lstatSync, readlinkSync } from "fs"; -import { mkdir, rm, symlink } from "fs/promises"; +import { mkdir, readlink, rm, symlink } from "fs/promises"; import { VerdaccioRegistry, bunEnv, bunExe, readdirSorted, runBunInstall } from "harness"; import { join } from "path"; const registry = new VerdaccioRegistry(); beforeAll(async () => { - setDefaultTimeout(10 * 60 * 1000); await registry.start(); }); @@ -771,3 +770,77 @@ test("successfully removes and corrects symlinks", async () => { join(".bun", "no-deps@1.0.0", "node_modules", "no-deps"), ); }); + +test("runs lifecycle scripts correctly", async () => { + // due to binary linking between preinstall and the remaining lifecycle scripts + // there is special handling for preinstall scripts we should test. + // 1. only preinstall + // 2. only postinstall (or any other script that isn't preinstall) + // 3. preinstall and any other script + + const { packageJson, packageDir } = await registry.createTestDir({ isolated: true }); + + await write( + packageJson, + JSON.stringify({ + name: "test-pkg-lifecycle-scripts", + dependencies: { + "lifecycle-preinstall": "1.0.0", + "lifecycle-postinstall": "1.0.0", + "all-lifecycle-scripts": "1.0.0", + }, + trustedDependencies: ["lifecycle-preinstall", "lifecycle-postinstall", "all-lifecycle-scripts"], + }), + ); + + await runBunInstall(bunEnv, packageDir); + + const [ + preinstallLink, + postinstallLink, + allScriptsLink, + preinstallFile, + postinstallFile, + allScriptsPreinstallFile, + allScriptsInstallFile, + allScriptsPostinstallFile, + bunDir, + lifecyclePreinstallDir, + lifecyclePostinstallDir, + allLifecycleScriptsDir, + ] = await Promise.all([ + readlink(join(packageDir, "node_modules", "lifecycle-preinstall")), + readlink(join(packageDir, "node_modules", "lifecycle-postinstall")), + readlink(join(packageDir, "node_modules", "all-lifecycle-scripts")), + file(join(packageDir, "node_modules", "lifecycle-preinstall", "preinstall.txt")).text(), + file(join(packageDir, "node_modules", "lifecycle-postinstall", "postinstall.txt")).text(), + file(join(packageDir, "node_modules", "all-lifecycle-scripts", "preinstall.txt")).text(), + file(join(packageDir, "node_modules", "all-lifecycle-scripts", "install.txt")).text(), + file(join(packageDir, "node_modules", "all-lifecycle-scripts", "postinstall.txt")).text(), + readdirSorted(join(packageDir, "node_modules", ".bun")), + readdirSorted(join(packageDir, "node_modules", ".bun", "lifecycle-preinstall@1.0.0", "node_modules")), + readdirSorted(join(packageDir, "node_modules", ".bun", "lifecycle-postinstall@1.0.0", "node_modules")), + readdirSorted(join(packageDir, "node_modules", ".bun", "all-lifecycle-scripts@1.0.0", "node_modules")), + ]); + + expect(preinstallLink).toBe(join(".bun", "lifecycle-preinstall@1.0.0", "node_modules", "lifecycle-preinstall")); + expect(postinstallLink).toBe(join(".bun", "lifecycle-postinstall@1.0.0", "node_modules", "lifecycle-postinstall")); + expect(allScriptsLink).toBe(join(".bun", "all-lifecycle-scripts@1.0.0", "node_modules", "all-lifecycle-scripts")); + + expect(preinstallFile).toBe("preinstall!"); + expect(postinstallFile).toBe("postinstall!"); + expect(allScriptsPreinstallFile).toBe("preinstall!"); + expect(allScriptsInstallFile).toBe("install!"); + expect(allScriptsPostinstallFile).toBe("postinstall!"); + + expect(bunDir).toEqual([ + "all-lifecycle-scripts@1.0.0", + "lifecycle-postinstall@1.0.0", + "lifecycle-preinstall@1.0.0", + "node_modules", + ]); + + expect(lifecyclePreinstallDir).toEqual(["lifecycle-preinstall"]); + expect(lifecyclePostinstallDir).toEqual(["lifecycle-postinstall"]); + expect(allLifecycleScriptsDir).toEqual(["all-lifecycle-scripts"]); +}); diff --git a/test/cli/install/migration/__snapshots__/yarn-lock-migration.test.ts.snap b/test/cli/install/migration/__snapshots__/yarn-lock-migration.test.ts.snap new file mode 100644 index 0000000000..262cab1003 --- /dev/null +++ b/test/cli/install/migration/__snapshots__/yarn-lock-migration.test.ts.snap @@ -0,0 +1,3163 @@ +// Bun Snapshot v1, https://bun.sh/docs/test/snapshots + +exports[`yarn.lock migration basic simple yarn.lock migration produces correct bun.lock: simple-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "simple-test", + "dependencies": { + "is-number": "^7.0.0", + }, + }, + }, + "packages": { + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + } +} +" +`; + +exports[`yarn.lock migration basic complex yarn.lock with multiple dependencies and versions: complex-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "complex-test", + "dependencies": { + "express": "^4.18.2", + "lodash": "^4.17.21", + }, + "devDependencies": { + "jest": "^29.0.0", + "typescript": "^5.0.0", + }, + "optionalDependencies": { + "fsevents": "^2.3.2", + }, + "peerDependencies": { + "react": "^18.0.0", + }, + }, + }, + "packages": { + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + + "array-flatten": ["array-flatten@1.1.1", "", {}, "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="], + + "body-parser": ["body-parser@1.20.1", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + + "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + + "cookie": ["cookie@0.5.0", "", {}, "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="], + + "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], + + "debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + + "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], + + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + + "encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + + "express": ["express@4.18.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", "serve-static": "1.15.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ=="], + + "finalhandler": ["finalhandler@1.2.0", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg=="], + + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + + "fsevents": ["fsevents@2.3.3", "", {}, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "get-intrinsic": ["get-intrinsic@1.2.2", "", { "dependencies": { "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" } }, "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA=="], + + "has-proto": ["has-proto@1.0.1", "", {}, "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="], + + "has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="], + + "hasown": ["hasown@2.0.0", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA=="], + + "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzBkH31s2EbTbs6iVFEJElQzL5aORl2ATXXJaOmXa2wAAAA=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + + "jest": ["jest@29.7.0", "", { "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", "import-local": "^3.0.2", "jest-cli": "^29.7.0" } }, "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + + "merge-descriptors": ["merge-descriptors@1.0.1", "", {}, "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="], + + "methods": ["methods@1.1.2", "", {}, "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="], + + "mime": ["mime@1.6.0", "", {}, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], + + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + + "path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="], + + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], + + "qs": ["qs@6.11.0", "", { "dependencies": { "side-channel": "^1.0.4" } }, "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q=="], + + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + + "raw-body": ["raw-body@2.5.1", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig=="], + + "react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "send": ["send@0.18.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg=="], + + "serve-static": ["serve-static@1.15.0", "", { "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.18.0" } }, "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + + "side-channel": ["side-channel@1.0.4", "", { "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" } }, "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw=="], + + "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + + "type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], + + "typescript": ["typescript@5.3.3", "", {}, "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + + "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + + "send/ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + } +} +" +`; + +exports[`yarn.lock migration basic yarn.lock with npm aliases: aliases-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "alias-test", + "dependencies": { + "@types/bun": "npm:bun-types@1.2.19", + "my-lodash": "npm:lodash@4.17.21", + }, + }, + }, + "packages": { + "@types/bun": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="], + + "@types/node": ["@types/node@20.11.5", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w=="], + + "my-lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + } +} +" +`; + +exports[`yarn.lock migration basic yarn.lock with resolutions: resolutions-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "resolutions-test", + "dependencies": { + "webpack": "^5.89.0", + }, + }, + }, + "overrides": { + "acorn": "8.11.3", + }, + "packages": { + "acorn": ["acorn@8.11.3", "", {}, "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg=="], + + "webpack": ["webpack@5.89.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", "@webassemblyjs/ast": "^1.11.5", "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.15.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" } }, "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw=="], + } +} +" +`; + +exports[`yarn.lock migration basic yarn.lock with workspace dependencies: workspace-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "workspace-root", + "dependencies": { + "lodash": "^4.17.21", + }, + }, + }, + "packages": { + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + } +} +" +`; + +exports[`yarn.lock migration basic yarn.lock with scoped packages and parent/child relationships: scoped-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "scoped-test", + "dependencies": { + "@babel/core": "^7.23.7", + "babel-loader": "^9.1.3", + }, + }, + }, + "packages": { + "@babel/code-frame": ["@babel/code-frame@7.23.5", "", { "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" } }, "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA=="], + + "@babel/core": ["@babel/core@7.23.7", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", "@babel/generator": "^7.23.6", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", "@babel/helpers": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/template": "^7.22.15", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw=="], + + "@babel/highlight": ["@babel/highlight@7.23.4", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" } }, "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A=="], + + "babel-loader": ["babel-loader@9.1.3", "", { "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" } }, "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw=="], + + "chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], + } +} +" +`; + +exports[`yarn.lock migration basic migration with realistic complex yarn.lock: complex-realistic-yarn-migration 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "complex-app", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@babel/core": "^7.20.0", + "webpack": "^5.75.0", + }, + "devDependencies": { + "@types/react": "^18.0.0", + "typescript": "^4.9.0", + "eslint": "^8.0.0", + }, + "optionalDependencies": { + "fsevents": "^2.3.2", + }, + "peerDependencies": { + "react": ">=16.8.0", + }, + }, + }, + "packages": { + "@babel/core": ["@babel/core@7.20.12", "", { "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", "@babel/generator": "^7.20.7", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-module-transforms": "^7.20.11", "@babel/helpers": "^7.20.7", "@babel/parser": "^7.20.7", "@babel/template": "^7.20.7", "@babel/traverse": "^7.20.12", "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" } }, "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg=="], + + "@types/react": ["@types/react@18.0.28", "", { "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew=="], + + "eslint": ["eslint@8.35.0", "", { "dependencies": { "@eslint/eslintrc": "^2.0.0", "@eslint/js": "8.35.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", "espree": "^9.4.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" } }, "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw=="], + + "fsevents": ["fsevents@2.3.2", "", {}, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + + "react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="], + + "react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], + + "scheduler": ["scheduler@0.23.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw=="], + + "semver": ["semver@6.3.0", "", {}, "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="], + + "typescript": ["typescript@4.9.5", "", {}, "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="], + + "webpack": ["webpack@5.76.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" } }, "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA=="], + } +} +" +`; + +exports[`bun pm migrate for existing yarn.lock yarn-cli-repo: yarn-cli-repo 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "yarn", + "dependencies": { + "@zkochan/cmd-shim": "^3.1.0", + "babel-runtime": "^6.26.0", + "bytes": "^3.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.1.0", + "cli-table3": "^0.4.0", + "commander": "^2.9.0", + "death": "^1.0.0", + "debug": "^3.0.0", + "deep-equal": "^1.0.1", + "detect-indent": "^5.0.0", + "dnscache": "^1.0.1", + "glob": "^7.1.1", + "gunzip-maybe": "^1.4.0", + "hash-for-dep": "^1.2.3", + "imports-loader": "^0.8.0", + "ini": "^1.3.4", + "inquirer": "^6.2.0", + "invariant": "^2.2.0", + "is-builtin-module": "^2.0.0", + "is-ci": "^1.0.10", + "is-webpack-bundle": "^1.0.0", + "js-yaml": "^3.13.1", + "leven": "^2.0.0", + "loud-rejection": "^1.2.0", + "micromatch": "^2.3.11", + "mkdirp": "^0.5.1", + "node-emoji": "^1.6.1", + "normalize-url": "^2.0.0", + "npm-logical-tree": "^1.2.1", + "object-path": "^0.11.2", + "proper-lockfile": "^2.0.0", + "puka": "^1.0.0", + "read": "^1.0.7", + "request": "^2.87.0", + "request-capture-har": "^1.2.2", + "rimraf": "^2.5.0", + "semver": "^5.1.0", + "ssri": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-bom": "^3.0.0", + "tar-fs": "^1.16.0", + "tar-stream": "^1.6.1", + "uuid": "^3.0.1", + "v8-compile-cache": "^2.0.0", + "validate-npm-package-license": "^3.0.4", + "yn": "^2.0.0", + }, + "devDependencies": { + "babel-core": "^6.26.0", + "babel-eslint": "^7.2.3", + "babel-loader": "^6.2.5", + "babel-plugin-array-includes": "^2.0.3", + "babel-plugin-inline-import": "^3.0.0", + "babel-plugin-transform-builtin-extend": "^1.1.2", + "babel-plugin-transform-inline-imports-commonjs": "^1.0.0", + "babel-plugin-transform-runtime": "^6.4.3", + "babel-preset-env": "^1.6.0", + "babel-preset-flow": "^6.23.0", + "babel-preset-stage-0": "^6.0.0", + "babylon": "^6.5.0", + "commitizen": "^2.9.6", + "cz-conventional-changelog": "^2.0.0", + "eslint": "^4.3.0", + "eslint-config-fb-strict": "^22.0.0", + "eslint-plugin-babel": "^5.0.0", + "eslint-plugin-flowtype": "^2.35.0", + "eslint-plugin-jasmine": "^2.6.2", + "eslint-plugin-jest": "^21.0.0", + "eslint-plugin-jsx-a11y": "^6.0.2", + "eslint-plugin-prefer-object-spread": "^1.2.1", + "eslint-plugin-prettier": "^2.1.2", + "eslint-plugin-react": "^7.1.0", + "eslint-plugin-relay": "^0.0.28", + "eslint-plugin-yarn-internal": "file:scripts/eslint-rules", + "execa": "^0.11.0", + "fancy-log": "^1.3.2", + "flow-bin": "^0.66.0", + "git-release-notes": "^3.0.0", + "gulp": "^4.0.0", + "gulp-babel": "^7.0.0", + "gulp-if": "^2.0.1", + "gulp-newer": "^1.0.0", + "gulp-plumber": "^1.0.1", + "gulp-sourcemaps": "^2.2.0", + "jest": "^22.4.4", + "jsinspect": "^0.12.6", + "minimatch": "^3.0.4", + "mock-stdin": "^0.3.0", + "prettier": "^1.5.2", + "string-replace-loader": "^2.1.1", + "temp": "^0.8.3", + "webpack": "^2.1.0-beta.25", + "yargs": "^6.3.0", + }, + }, + }, + "overrides": { + "sshpk": "^1.14.2", + }, + "packages": { + "@babel/code-frame": ["@babel/code-frame@7.0.0-beta.55", "", { "dependencies": { "@babel/highlight": "7.0.0-beta.55" } }, "sha1-cfUw57AQr163p993UveJId1X6e4="], + + "@babel/highlight": ["@babel/highlight@7.0.0-beta.55", "", { "dependencies": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^3.0.0" } }, "sha1-mIZTZH1inCYdrhVudNXwJSulIMA="], + + "@gulp-sourcemaps/identity-map": ["@gulp-sourcemaps/identity-map@1.0.2", "", { "dependencies": { "acorn": "^5.0.3", "css": "^2.2.1", "normalize-path": "^2.1.1", "source-map": "^0.6.0", "through2": "^2.0.3" } }, "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ=="], + + "@gulp-sourcemaps/map-sources": ["@gulp-sourcemaps/map-sources@1.0.0", "", { "dependencies": { "normalize-path": "^2.0.1", "through2": "^2.0.3" } }, "sha1-iQrnxdjId/bThIYCFazp1+yUW9o="], + + "@zkochan/cmd-shim": ["@zkochan/cmd-shim@3.1.0", "", { "dependencies": { "is-windows": "^1.0.0", "mkdirp-promise": "^5.0.1", "mz": "^2.5.0" } }, "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg=="], + + "abab": ["abab@2.0.0", "", {}, "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w=="], + + "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "acorn": ["acorn@5.7.1", "", {}, "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ=="], + + "acorn-dynamic-import": ["acorn-dynamic-import@2.0.2", "", { "dependencies": { "acorn": "^4.0.3" } }, "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ="], + + "acorn-globals": ["acorn-globals@4.1.0", "", { "dependencies": { "acorn": "^5.0.0" } }, "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ=="], + + "acorn-jsx": ["acorn-jsx@3.0.1", "", { "dependencies": { "acorn": "^3.0.4" } }, "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s="], + + "ajv": ["ajv@5.5.2", "", { "dependencies": { "co": "^4.6.0", "fast-deep-equal": "^1.0.0", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.3.0" } }, "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU="], + + "ajv-keywords": ["ajv-keywords@1.5.1", "", {}, "sha1-MU3QpLM2j609/NxU7eYXG4htrzw="], + + "align-text": ["align-text@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2", "longest": "^1.0.1", "repeat-string": "^1.5.2" } }, "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc="], + + "amdefine": ["amdefine@1.0.1", "", {}, "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="], + + "ansi-colors": ["ansi-colors@1.1.0", "", { "dependencies": { "ansi-wrap": "^0.1.0" } }, "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA=="], + + "ansi-cyan": ["ansi-cyan@0.1.1", "", { "dependencies": { "ansi-wrap": "0.1.0" } }, "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM="], + + "ansi-escapes": ["ansi-escapes@3.1.0", "", {}, "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw=="], + + "ansi-gray": ["ansi-gray@0.1.1", "", { "dependencies": { "ansi-wrap": "0.1.0" } }, "sha1-KWLPVOyXksSFEKPetSRDaGHvclE="], + + "ansi-red": ["ansi-red@0.1.1", "", { "dependencies": { "ansi-wrap": "0.1.0" } }, "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw="], + + "ansi-regex": ["ansi-regex@3.0.0", "", {}, "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="], + + "ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], + + "ansi-wrap": ["ansi-wrap@0.1.0", "", {}, "sha1-qCJQ3bABXponyoLoLqYDu/pF768="], + + "any-promise": ["any-promise@1.3.0", "", {}, "sha1-q8av7tzqUugJzcA3au0845Y10X8="], + + "anymatch": ["anymatch@2.0.0", "", { "dependencies": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" } }, "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw=="], + + "append-buffer": ["append-buffer@1.0.2", "", { "dependencies": { "buffer-equal": "^1.0.0" } }, "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE="], + + "append-transform": ["append-transform@1.0.0", "", { "dependencies": { "default-require-extensions": "^2.0.0" } }, "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw=="], + + "aproba": ["aproba@1.2.0", "", {}, "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="], + + "archy": ["archy@1.0.0", "", {}, "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="], + + "are-we-there-yet": ["are-we-there-yet@1.1.5", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" } }, "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w=="], + + "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + + "aria-query": ["aria-query@3.0.0", "", { "dependencies": { "ast-types-flow": "0.0.7", "commander": "^2.11.0" } }, "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w="], + + "arr-diff": ["arr-diff@2.0.0", "", { "dependencies": { "arr-flatten": "^1.0.1" } }, "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8="], + + "arr-filter": ["arr-filter@1.1.2", "", { "dependencies": { "make-iterator": "^1.0.0" } }, "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4="], + + "arr-flatten": ["arr-flatten@1.1.0", "", {}, "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="], + + "arr-map": ["arr-map@2.0.2", "", { "dependencies": { "make-iterator": "^1.0.0" } }, "sha1-Onc0X/wc814qkYJWAfnljy4kysQ="], + + "arr-union": ["arr-union@3.1.0", "", {}, "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="], + + "array-each": ["array-each@1.0.1", "", {}, "sha1-p5SvDAWrF1KEbudTofIRoFugxE8="], + + "array-equal": ["array-equal@1.0.0", "", {}, "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM="], + + "array-find-index": ["array-find-index@1.0.2", "", {}, "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="], + + "array-includes": ["array-includes@3.0.3", "", { "dependencies": { "define-properties": "^1.1.2", "es-abstract": "^1.7.0" } }, "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0="], + + "array-initial": ["array-initial@1.1.0", "", { "dependencies": { "array-slice": "^1.0.0", "is-number": "^4.0.0" } }, "sha1-L6dLJnOTccOUe9enrcc74zSz15U="], + + "array-last": ["array-last@1.3.0", "", { "dependencies": { "is-number": "^4.0.0" } }, "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg=="], + + "array-slice": ["array-slice@1.1.0", "", {}, "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w=="], + + "array-sort": ["array-sort@1.0.0", "", { "dependencies": { "default-compare": "^1.0.0", "get-value": "^2.0.6", "kind-of": "^5.0.2" } }, "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg=="], + + "array-union": ["array-union@1.0.2", "", { "dependencies": { "array-uniq": "^1.0.1" } }, "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk="], + + "array-uniq": ["array-uniq@1.0.3", "", {}, "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="], + + "array-unique": ["array-unique@0.2.1", "", {}, "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="], + + "arrify": ["arrify@1.0.1", "", {}, "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="], + + "asap": ["asap@2.0.6", "", {}, "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="], + + "asn1": ["asn1@0.2.4", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg=="], + + "asn1.js": ["asn1.js@4.10.1", "", { "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw=="], + + "assert": ["assert@1.4.1", "", { "dependencies": { "util": "0.10.3" } }, "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE="], + + "assert-plus": ["assert-plus@1.0.0", "", {}, "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="], + + "assign-symbols": ["assign-symbols@1.0.0", "", {}, "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="], + + "ast-types-flow": ["ast-types-flow@0.0.7", "", {}, "sha1-9wtzXGvKGlycItmCw+Oef+ujva0="], + + "astral-regex": ["astral-regex@1.0.0", "", {}, "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg=="], + + "async": ["async@2.6.1", "", { "dependencies": { "lodash": "^4.17.10" } }, "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ=="], + + "async-done": ["async-done@1.3.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.2", "process-nextick-args": "^1.0.7", "stream-exhaust": "^1.0.1" } }, "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg=="], + + "async-each": ["async-each@1.0.1", "", {}, "sha1-GdOGodntxufByF04iu28xW0zYC0="], + + "async-limiter": ["async-limiter@1.0.0", "", {}, "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="], + + "async-settle": ["async-settle@1.0.0", "", { "dependencies": { "async-done": "^1.2.2" } }, "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha1-x57Zf380y48robyXkLzDZkdLS3k="], + + "atob": ["atob@2.1.1", "", {}, "sha1-ri1acpR38onWDdf5amMUoi3Wwio="], + + "aws-sign2": ["aws-sign2@0.7.0", "", {}, "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="], + + "aws4": ["aws4@1.7.0", "", {}, "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="], + + "axobject-query": ["axobject-query@2.0.1", "", { "dependencies": { "ast-types-flow": "0.0.7" } }, "sha1-Bd+nBa2orZ25k/polvItOVsLCgc="], + + "babel-code-frame": ["babel-code-frame@6.26.0", "", { "dependencies": { "chalk": "^1.1.3", "esutils": "^2.0.2", "js-tokens": "^3.0.2" } }, "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s="], + + "babel-core": ["babel-core@6.26.3", "", { "dependencies": { "babel-code-frame": "^6.26.0", "babel-generator": "^6.26.0", "babel-helpers": "^6.24.1", "babel-messages": "^6.23.0", "babel-register": "^6.26.0", "babel-runtime": "^6.26.0", "babel-template": "^6.26.0", "babel-traverse": "^6.26.0", "babel-types": "^6.26.0", "babylon": "^6.18.0", "convert-source-map": "^1.5.1", "debug": "^2.6.9", "json5": "^0.5.1", "lodash": "^4.17.4", "minimatch": "^3.0.4", "path-is-absolute": "^1.0.1", "private": "^0.1.8", "slash": "^1.0.0", "source-map": "^0.5.7" } }, "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA=="], + + "babel-eslint": ["babel-eslint@7.2.3", "", { "dependencies": { "babel-code-frame": "^6.22.0", "babel-traverse": "^6.23.1", "babel-types": "^6.23.0", "babylon": "^6.17.0" } }, "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc="], + + "babel-generator": ["babel-generator@6.26.1", "", { "dependencies": { "babel-messages": "^6.23.0", "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "detect-indent": "^4.0.0", "jsesc": "^1.3.0", "lodash": "^4.17.4", "source-map": "^0.5.7", "trim-right": "^1.0.1" } }, "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA=="], + + "babel-helper-bindify-decorators": ["babel-helper-bindify-decorators@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA="], + + "babel-helper-builder-binary-assignment-operator-visitor": ["babel-helper-builder-binary-assignment-operator-visitor@6.24.1", "", { "dependencies": { "babel-helper-explode-assignable-expression": "^6.24.1", "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ="], + + "babel-helper-call-delegate": ["babel-helper-call-delegate@6.24.1", "", { "dependencies": { "babel-helper-hoist-variables": "^6.24.1", "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340="], + + "babel-helper-define-map": ["babel-helper-define-map@6.26.0", "", { "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "lodash": "^4.17.4" } }, "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8="], + + "babel-helper-explode-assignable-expression": ["babel-helper-explode-assignable-expression@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-8luCz33BBDPFX3BZLVdGQArCLKo="], + + "babel-helper-explode-class": ["babel-helper-explode-class@6.24.1", "", { "dependencies": { "babel-helper-bindify-decorators": "^6.24.1", "babel-runtime": "^6.22.0", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes="], + + "babel-helper-function-name": ["babel-helper-function-name@6.24.1", "", { "dependencies": { "babel-helper-get-function-arity": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk="], + + "babel-helper-get-function-arity": ["babel-helper-get-function-arity@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0="], + + "babel-helper-hoist-variables": ["babel-helper-hoist-variables@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-HssnaJydJVE+rbyZFKc/VAi+enY="], + + "babel-helper-optimise-call-expression": ["babel-helper-optimise-call-expression@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc="], + + "babel-helper-regex": ["babel-helper-regex@6.26.0", "", { "dependencies": { "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "lodash": "^4.17.4" } }, "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI="], + + "babel-helper-remap-async-to-generator": ["babel-helper-remap-async-to-generator@6.24.1", "", { "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs="], + + "babel-helper-replace-supers": ["babel-helper-replace-supers@6.24.1", "", { "dependencies": { "babel-helper-optimise-call-expression": "^6.24.1", "babel-messages": "^6.23.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-v22/5Dk40XNpohPKiov3S2qQqxo="], + + "babel-helpers": ["babel-helpers@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI="], + + "babel-jest": ["babel-jest@22.4.4", "", { "dependencies": { "babel-plugin-istanbul": "^4.1.5", "babel-preset-jest": "^22.4.4" } }, "sha512-A9NB6/lZhYyypR9ATryOSDcqBaqNdzq4U+CN+/wcMsLcmKkPxQEoTKLajGfd3IkxNyVBT8NewUK2nWyGbSzHEQ=="], + + "babel-loader": ["babel-loader@6.4.1", "", { "dependencies": { "find-cache-dir": "^0.1.1", "loader-utils": "^0.2.16", "mkdirp": "^0.5.1", "object-assign": "^4.0.1" } }, "sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo="], + + "babel-messages": ["babel-messages@6.23.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4="], + + "babel-plugin-array-includes": ["babel-plugin-array-includes@2.0.3", "", {}, "sha1-z1RS6Bx7gD+3lZ8QRayI4uwo/3Y="], + + "babel-plugin-check-es2015-constants": ["babel-plugin-check-es2015-constants@6.22.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o="], + + "babel-plugin-inline-import": ["babel-plugin-inline-import@3.0.0", "", { "dependencies": { "require-resolve": "0.0.2" } }, "sha512-thnykl4FMb8QjMjVCuZoUmAM7r2mnTn5qJwrryCvDv6rugbJlTHZMctdjDtEgD0WBAXJOLJSGXN3loooEwx7UQ=="], + + "babel-plugin-istanbul": ["babel-plugin-istanbul@4.1.6", "", { "dependencies": { "babel-plugin-syntax-object-rest-spread": "^6.13.0", "find-up": "^2.1.0", "istanbul-lib-instrument": "^1.10.1", "test-exclude": "^4.2.1" } }, "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ=="], + + "babel-plugin-jest-hoist": ["babel-plugin-jest-hoist@22.4.4", "", {}, "sha512-DUvGfYaAIlkdnygVIEl0O4Av69NtuQWcrjMOv6DODPuhuGLDnbsARz3AwiiI/EkIMMlxQDUcrZ9yoyJvTNjcVQ=="], + + "babel-plugin-syntax-async-functions": ["babel-plugin-syntax-async-functions@6.13.0", "", {}, "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="], + + "babel-plugin-syntax-async-generators": ["babel-plugin-syntax-async-generators@6.13.0", "", {}, "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o="], + + "babel-plugin-syntax-class-constructor-call": ["babel-plugin-syntax-class-constructor-call@6.18.0", "", {}, "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY="], + + "babel-plugin-syntax-class-properties": ["babel-plugin-syntax-class-properties@6.13.0", "", {}, "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94="], + + "babel-plugin-syntax-decorators": ["babel-plugin-syntax-decorators@6.13.0", "", {}, "sha1-MSVjtNvePMgGzuPkFszurd0RrAs="], + + "babel-plugin-syntax-do-expressions": ["babel-plugin-syntax-do-expressions@6.13.0", "", {}, "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0="], + + "babel-plugin-syntax-dynamic-import": ["babel-plugin-syntax-dynamic-import@6.18.0", "", {}, "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo="], + + "babel-plugin-syntax-exponentiation-operator": ["babel-plugin-syntax-exponentiation-operator@6.13.0", "", {}, "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4="], + + "babel-plugin-syntax-export-extensions": ["babel-plugin-syntax-export-extensions@6.13.0", "", {}, "sha1-cKFITw+QiaToStRLrDU8lbmxJyE="], + + "babel-plugin-syntax-flow": ["babel-plugin-syntax-flow@6.18.0", "", {}, "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0="], + + "babel-plugin-syntax-function-bind": ["babel-plugin-syntax-function-bind@6.13.0", "", {}, "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y="], + + "babel-plugin-syntax-object-rest-spread": ["babel-plugin-syntax-object-rest-spread@6.13.0", "", {}, "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U="], + + "babel-plugin-syntax-trailing-function-commas": ["babel-plugin-syntax-trailing-function-commas@6.22.0", "", {}, "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="], + + "babel-plugin-transform-async-generator-functions": ["babel-plugin-transform-async-generator-functions@6.24.1", "", { "dependencies": { "babel-helper-remap-async-to-generator": "^6.24.1", "babel-plugin-syntax-async-generators": "^6.5.0", "babel-runtime": "^6.22.0" } }, "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds="], + + "babel-plugin-transform-async-to-generator": ["babel-plugin-transform-async-to-generator@6.24.1", "", { "dependencies": { "babel-helper-remap-async-to-generator": "^6.24.1", "babel-plugin-syntax-async-functions": "^6.8.0", "babel-runtime": "^6.22.0" } }, "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E="], + + "babel-plugin-transform-builtin-extend": ["babel-plugin-transform-builtin-extend@1.1.2", "", { "dependencies": { "babel-runtime": "^6.2.0", "babel-template": "^6.3.0" } }, "sha1-Xpb+z1i4+h7XTvytiEdbKvPJEW4="], + + "babel-plugin-transform-class-constructor-call": ["babel-plugin-transform-class-constructor-call@6.24.1", "", { "dependencies": { "babel-plugin-syntax-class-constructor-call": "^6.18.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk="], + + "babel-plugin-transform-class-properties": ["babel-plugin-transform-class-properties@6.24.1", "", { "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-plugin-syntax-class-properties": "^6.8.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw="], + + "babel-plugin-transform-decorators": ["babel-plugin-transform-decorators@6.24.1", "", { "dependencies": { "babel-helper-explode-class": "^6.24.1", "babel-plugin-syntax-decorators": "^6.13.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0="], + + "babel-plugin-transform-do-expressions": ["babel-plugin-transform-do-expressions@6.22.0", "", { "dependencies": { "babel-plugin-syntax-do-expressions": "^6.8.0", "babel-runtime": "^6.22.0" } }, "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs="], + + "babel-plugin-transform-es2015-arrow-functions": ["babel-plugin-transform-es2015-arrow-functions@6.22.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE="], + + "babel-plugin-transform-es2015-block-scoped-functions": ["babel-plugin-transform-es2015-block-scoped-functions@6.22.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-u8UbSflk1wy42OC5ToICRs46YUE="], + + "babel-plugin-transform-es2015-block-scoping": ["babel-plugin-transform-es2015-block-scoping@6.26.0", "", { "dependencies": { "babel-runtime": "^6.26.0", "babel-template": "^6.26.0", "babel-traverse": "^6.26.0", "babel-types": "^6.26.0", "lodash": "^4.17.4" } }, "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8="], + + "babel-plugin-transform-es2015-classes": ["babel-plugin-transform-es2015-classes@6.24.1", "", { "dependencies": { "babel-helper-define-map": "^6.24.1", "babel-helper-function-name": "^6.24.1", "babel-helper-optimise-call-expression": "^6.24.1", "babel-helper-replace-supers": "^6.24.1", "babel-messages": "^6.23.0", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs="], + + "babel-plugin-transform-es2015-computed-properties": ["babel-plugin-transform-es2015-computed-properties@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM="], + + "babel-plugin-transform-es2015-destructuring": ["babel-plugin-transform-es2015-destructuring@6.23.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0="], + + "babel-plugin-transform-es2015-duplicate-keys": ["babel-plugin-transform-es2015-duplicate-keys@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-c+s9MQypaePvnskcU3QabxV2Qj4="], + + "babel-plugin-transform-es2015-for-of": ["babel-plugin-transform-es2015-for-of@6.23.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE="], + + "babel-plugin-transform-es2015-function-name": ["babel-plugin-transform-es2015-function-name@6.24.1", "", { "dependencies": { "babel-helper-function-name": "^6.24.1", "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos="], + + "babel-plugin-transform-es2015-literals": ["babel-plugin-transform-es2015-literals@6.22.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4="], + + "babel-plugin-transform-es2015-modules-amd": ["babel-plugin-transform-es2015-modules-amd@6.24.1", "", { "dependencies": { "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ="], + + "babel-plugin-transform-es2015-modules-commonjs": ["babel-plugin-transform-es2015-modules-commonjs@6.26.2", "", { "dependencies": { "babel-plugin-transform-strict-mode": "^6.24.1", "babel-runtime": "^6.26.0", "babel-template": "^6.26.0", "babel-types": "^6.26.0" } }, "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q=="], + + "babel-plugin-transform-es2015-modules-systemjs": ["babel-plugin-transform-es2015-modules-systemjs@6.24.1", "", { "dependencies": { "babel-helper-hoist-variables": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM="], + + "babel-plugin-transform-es2015-modules-umd": ["babel-plugin-transform-es2015-modules-umd@6.24.1", "", { "dependencies": { "babel-plugin-transform-es2015-modules-amd": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, "sha1-rJl+YoXNGO1hdq22B9YCNErThGg="], + + "babel-plugin-transform-es2015-object-super": ["babel-plugin-transform-es2015-object-super@6.24.1", "", { "dependencies": { "babel-helper-replace-supers": "^6.24.1", "babel-runtime": "^6.22.0" } }, "sha1-JM72muIcuDp/hgPa0CH1cusnj40="], + + "babel-plugin-transform-es2015-parameters": ["babel-plugin-transform-es2015-parameters@6.24.1", "", { "dependencies": { "babel-helper-call-delegate": "^6.24.1", "babel-helper-get-function-arity": "^6.24.1", "babel-runtime": "^6.22.0", "babel-template": "^6.24.1", "babel-traverse": "^6.24.1", "babel-types": "^6.24.1" } }, "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys="], + + "babel-plugin-transform-es2015-shorthand-properties": ["babel-plugin-transform-es2015-shorthand-properties@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA="], + + "babel-plugin-transform-es2015-spread": ["babel-plugin-transform-es2015-spread@6.22.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-1taKmfia7cRTbIGlQujdnxdG+NE="], + + "babel-plugin-transform-es2015-sticky-regex": ["babel-plugin-transform-es2015-sticky-regex@6.24.1", "", { "dependencies": { "babel-helper-regex": "^6.24.1", "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-AMHNsaynERLN8M9hJsLta0V8zbw="], + + "babel-plugin-transform-es2015-template-literals": ["babel-plugin-transform-es2015-template-literals@6.22.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0="], + + "babel-plugin-transform-es2015-typeof-symbol": ["babel-plugin-transform-es2015-typeof-symbol@6.23.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I="], + + "babel-plugin-transform-es2015-unicode-regex": ["babel-plugin-transform-es2015-unicode-regex@6.24.1", "", { "dependencies": { "babel-helper-regex": "^6.24.1", "babel-runtime": "^6.22.0", "regexpu-core": "^2.0.0" } }, "sha1-04sS9C6nMj9yk4fxinxa4frrNek="], + + "babel-plugin-transform-exponentiation-operator": ["babel-plugin-transform-exponentiation-operator@6.24.1", "", { "dependencies": { "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", "babel-plugin-syntax-exponentiation-operator": "^6.8.0", "babel-runtime": "^6.22.0" } }, "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4="], + + "babel-plugin-transform-export-extensions": ["babel-plugin-transform-export-extensions@6.22.0", "", { "dependencies": { "babel-plugin-syntax-export-extensions": "^6.8.0", "babel-runtime": "^6.22.0" } }, "sha1-U3OLR+deghhYnuqUbLvTkQm75lM="], + + "babel-plugin-transform-flow-strip-types": ["babel-plugin-transform-flow-strip-types@6.22.0", "", { "dependencies": { "babel-plugin-syntax-flow": "^6.18.0", "babel-runtime": "^6.22.0" } }, "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988="], + + "babel-plugin-transform-function-bind": ["babel-plugin-transform-function-bind@6.22.0", "", { "dependencies": { "babel-plugin-syntax-function-bind": "^6.8.0", "babel-runtime": "^6.22.0" } }, "sha1-xvuOlqwpajELjPjqQBRiQH3fapc="], + + "babel-plugin-transform-inline-imports-commonjs": ["babel-plugin-transform-inline-imports-commonjs@1.2.0", "", { "dependencies": { "babel-plugin-transform-strict-mode": "^6.8.0", "builtin-modules": "^1.1.1" } }, "sha1-IMfRkrr8VMhyc4bjOH2O5O8Z5qU="], + + "babel-plugin-transform-object-rest-spread": ["babel-plugin-transform-object-rest-spread@6.26.0", "", { "dependencies": { "babel-plugin-syntax-object-rest-spread": "^6.8.0", "babel-runtime": "^6.26.0" } }, "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY="], + + "babel-plugin-transform-regenerator": ["babel-plugin-transform-regenerator@6.26.0", "", { "dependencies": { "regenerator-transform": "^0.10.0" } }, "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8="], + + "babel-plugin-transform-runtime": ["babel-plugin-transform-runtime@6.23.0", "", { "dependencies": { "babel-runtime": "^6.22.0" } }, "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4="], + + "babel-plugin-transform-strict-mode": ["babel-plugin-transform-strict-mode@6.24.1", "", { "dependencies": { "babel-runtime": "^6.22.0", "babel-types": "^6.24.1" } }, "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g="], + + "babel-polyfill": ["babel-polyfill@6.23.0", "", { "dependencies": { "babel-runtime": "^6.22.0", "core-js": "^2.4.0", "regenerator-runtime": "^0.10.0" } }, "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0="], + + "babel-preset-env": ["babel-preset-env@1.7.0", "", { "dependencies": { "babel-plugin-check-es2015-constants": "^6.22.0", "babel-plugin-syntax-trailing-function-commas": "^6.22.0", "babel-plugin-transform-async-to-generator": "^6.22.0", "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", "babel-plugin-transform-es2015-block-scoping": "^6.23.0", "babel-plugin-transform-es2015-classes": "^6.23.0", "babel-plugin-transform-es2015-computed-properties": "^6.22.0", "babel-plugin-transform-es2015-destructuring": "^6.23.0", "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", "babel-plugin-transform-es2015-for-of": "^6.23.0", "babel-plugin-transform-es2015-function-name": "^6.22.0", "babel-plugin-transform-es2015-literals": "^6.22.0", "babel-plugin-transform-es2015-modules-amd": "^6.22.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", "babel-plugin-transform-es2015-modules-umd": "^6.23.0", "babel-plugin-transform-es2015-object-super": "^6.22.0", "babel-plugin-transform-es2015-parameters": "^6.23.0", "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", "babel-plugin-transform-es2015-spread": "^6.22.0", "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", "babel-plugin-transform-es2015-template-literals": "^6.22.0", "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", "babel-plugin-transform-exponentiation-operator": "^6.22.0", "babel-plugin-transform-regenerator": "^6.22.0", "browserslist": "^3.2.6", "invariant": "^2.2.2", "semver": "^5.3.0" } }, "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg=="], + + "babel-preset-flow": ["babel-preset-flow@6.23.0", "", { "dependencies": { "babel-plugin-transform-flow-strip-types": "^6.22.0" } }, "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0="], + + "babel-preset-jest": ["babel-preset-jest@22.4.4", "", { "dependencies": { "babel-plugin-jest-hoist": "^22.4.4", "babel-plugin-syntax-object-rest-spread": "^6.13.0" } }, "sha512-+dxMtOFwnSYWfum0NaEc0O03oSdwBsjx4tMSChRDPGwu/4wSY6Q6ANW3wkjKpJzzguaovRs/DODcT4hbSN8yiA=="], + + "babel-preset-stage-0": ["babel-preset-stage-0@6.24.1", "", { "dependencies": { "babel-plugin-transform-do-expressions": "^6.22.0", "babel-plugin-transform-function-bind": "^6.22.0", "babel-preset-stage-1": "^6.24.1" } }, "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo="], + + "babel-preset-stage-1": ["babel-preset-stage-1@6.24.1", "", { "dependencies": { "babel-plugin-transform-class-constructor-call": "^6.24.1", "babel-plugin-transform-export-extensions": "^6.22.0", "babel-preset-stage-2": "^6.24.1" } }, "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A="], + + "babel-preset-stage-2": ["babel-preset-stage-2@6.24.1", "", { "dependencies": { "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-decorators": "^6.24.1", "babel-preset-stage-3": "^6.24.1" } }, "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE="], + + "babel-preset-stage-3": ["babel-preset-stage-3@6.24.1", "", { "dependencies": { "babel-plugin-syntax-trailing-function-commas": "^6.22.0", "babel-plugin-transform-async-generator-functions": "^6.24.1", "babel-plugin-transform-async-to-generator": "^6.24.1", "babel-plugin-transform-exponentiation-operator": "^6.24.1", "babel-plugin-transform-object-rest-spread": "^6.22.0" } }, "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U="], + + "babel-register": ["babel-register@6.26.0", "", { "dependencies": { "babel-core": "^6.26.0", "babel-runtime": "^6.26.0", "core-js": "^2.5.0", "home-or-tmp": "^2.0.0", "lodash": "^4.17.4", "mkdirp": "^0.5.1", "source-map-support": "^0.4.15" } }, "sha1-btAhFz4vy0htestFxgCahW9kcHE="], + + "babel-runtime": ["babel-runtime@6.26.0", "", { "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" } }, "sha1-llxwWGaOgrVde/4E/yM3vItWR/4="], + + "babel-template": ["babel-template@6.26.0", "", { "dependencies": { "babel-runtime": "^6.26.0", "babel-traverse": "^6.26.0", "babel-types": "^6.26.0", "babylon": "^6.18.0", "lodash": "^4.17.4" } }, "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI="], + + "babel-traverse": ["babel-traverse@6.26.0", "", { "dependencies": { "babel-code-frame": "^6.26.0", "babel-messages": "^6.23.0", "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", "babylon": "^6.18.0", "debug": "^2.6.8", "globals": "^9.18.0", "invariant": "^2.2.2", "lodash": "^4.17.4" } }, "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4="], + + "babel-types": ["babel-types@6.26.0", "", { "dependencies": { "babel-runtime": "^6.26.0", "esutils": "^2.0.2", "lodash": "^4.17.4", "to-fast-properties": "^1.0.3" } }, "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc="], + + "babylon": ["babylon@6.18.0", "", {}, "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="], + + "bach": ["bach@1.2.0", "", { "dependencies": { "arr-filter": "^1.1.1", "arr-flatten": "^1.0.1", "arr-map": "^2.0.0", "array-each": "^1.0.0", "array-initial": "^1.0.0", "array-last": "^1.1.1", "async-done": "^1.2.2", "async-settle": "^1.0.0", "now-and-later": "^2.0.0" } }, "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA="], + + "balanced-match": ["balanced-match@1.0.0", "", {}, "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="], + + "base": ["base@0.11.2", "", { "dependencies": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", "component-emitter": "^1.2.1", "define-property": "^1.0.0", "isobject": "^3.0.1", "mixin-deep": "^1.2.0", "pascalcase": "^0.1.1" } }, "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg=="], + + "base64-js": ["base64-js@1.3.0", "", {}, "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="], + + "bcrypt-pbkdf": ["bcrypt-pbkdf@1.0.2", "", { "dependencies": { "tweetnacl": "^0.14.3" } }, "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4="], + + "big.js": ["big.js@3.2.0", "", {}, "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="], + + "binary-extensions": ["binary-extensions@1.11.0", "", {}, "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU="], + + "bl": ["bl@1.2.2", "", { "dependencies": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" } }, "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA=="], + + "bn.js": ["bn.js@4.11.8", "", {}, "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "braces": ["braces@1.8.5", "", { "dependencies": { "expand-range": "^1.8.1", "preserve": "^0.2.0", "repeat-element": "^1.1.2" } }, "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc="], + + "broccoli-kitchen-sink-helpers": ["broccoli-kitchen-sink-helpers@0.3.1", "", { "dependencies": { "glob": "^5.0.10", "mkdirp": "^0.5.1" } }, "sha1-d8fBgZS5ZkFj7E/O4nk0RJJuDAY="], + + "brorand": ["brorand@1.1.0", "", {}, "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="], + + "browser-process-hrtime": ["browser-process-hrtime@0.1.2", "", {}, "sha1-Ql1opY00R/AqBKqJQYf86K+Le44="], + + "browser-resolve": ["browser-resolve@1.11.3", "", { "dependencies": { "resolve": "1.1.7" } }, "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ=="], + + "browserify-aes": ["browserify-aes@1.2.0", "", { "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.3", "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA=="], + + "browserify-cipher": ["browserify-cipher@1.0.1", "", { "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", "evp_bytestokey": "^1.0.0" } }, "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w=="], + + "browserify-des": ["browserify-des@1.0.2", "", { "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A=="], + + "browserify-rsa": ["browserify-rsa@4.0.1", "", { "dependencies": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" } }, "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ="], + + "browserify-sign": ["browserify-sign@4.0.4", "", { "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" } }, "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg="], + + "browserify-zlib": ["browserify-zlib@0.1.4", "", { "dependencies": { "pako": "~0.2.0" } }, "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0="], + + "browserslist": ["browserslist@3.2.8", "", { "dependencies": { "caniuse-lite": "^1.0.30000844", "electron-to-chromium": "^1.3.47" } }, "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ=="], + + "bser": ["bser@2.0.0", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk="], + + "buffer": ["buffer@4.9.1", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg="], + + "buffer-alloc": ["buffer-alloc@1.2.0", "", { "dependencies": { "buffer-alloc-unsafe": "^1.1.0", "buffer-fill": "^1.0.0" } }, "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow=="], + + "buffer-alloc-unsafe": ["buffer-alloc-unsafe@1.1.0", "", {}, "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="], + + "buffer-equal": ["buffer-equal@1.0.0", "", {}, "sha1-WWFrSYME1Var1GaWayLu2j7KX74="], + + "buffer-fill": ["buffer-fill@1.0.0", "", {}, "sha1-+PeLdniYiO858gXNY39o5wISKyw="], + + "buffer-from": ["buffer-from@1.1.1", "", {}, "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="], + + "buffer-xor": ["buffer-xor@1.0.3", "", {}, "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="], + + "builtin-modules": ["builtin-modules@1.1.1", "", {}, "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="], + + "builtin-status-codes": ["builtin-status-codes@3.0.0", "", {}, "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="], + + "bytes": ["bytes@3.0.0", "", {}, "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="], + + "cache-base": ["cache-base@1.0.1", "", { "dependencies": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", "get-value": "^2.0.6", "has-value": "^1.0.0", "isobject": "^3.0.1", "set-value": "^2.0.0", "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" } }, "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ=="], + + "cachedir": ["cachedir@1.3.0", "", { "dependencies": { "os-homedir": "^1.0.1" } }, "sha512-O1ji32oyON9laVPJL1IZ5bmwd2cB46VfpxkDequezH+15FDzzVddEyrGEeX4WusDSqKxdyFdDQDEG1yo1GoWkg=="], + + "caller-path": ["caller-path@0.1.0", "", { "dependencies": { "callsites": "^0.2.0" } }, "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8="], + + "callsites": ["callsites@0.2.0", "", {}, "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo="], + + "camelcase": ["camelcase@4.1.0", "", {}, "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="], + + "caniuse-lite": ["caniuse-lite@1.0.30000865", "", {}, "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw=="], + + "capture-exit": ["capture-exit@1.2.0", "", { "dependencies": { "rsvp": "^3.3.3" } }, "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28="], + + "caseless": ["caseless@0.12.0", "", {}, "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="], + + "center-align": ["center-align@0.1.3", "", { "dependencies": { "align-text": "^0.1.3", "lazy-cache": "^1.0.3" } }, "sha1-qg0yYptu6XIgBBHL1EYckHvCt60="], + + "chalk": ["chalk@2.3.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ=="], + + "chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="], + + "chokidar": ["chokidar@2.0.4", "", { "dependencies": { "anymatch": "^2.0.0", "async-each": "^1.0.0", "braces": "^2.3.0", "glob-parent": "^3.1.0", "inherits": "^2.0.1", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", "lodash.debounce": "^4.0.8", "normalize-path": "^2.1.1", "path-is-absolute": "^1.0.0", "readdirp": "^2.0.0", "upath": "^1.0.5" }, "optionalDependencies": { "fsevents": "^1.2.2" } }, "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ=="], + + "chownr": ["chownr@1.0.1", "", {}, "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="], + + "ci-info": ["ci-info@1.1.3", "", {}, "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg=="], + + "cipher-base": ["cipher-base@1.0.4", "", { "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q=="], + + "circular-json": ["circular-json@0.3.3", "", {}, "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A=="], + + "class-utils": ["class-utils@0.3.6", "", { "dependencies": { "arr-union": "^3.1.0", "define-property": "^0.2.5", "isobject": "^3.0.0", "static-extend": "^0.1.1" } }, "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg=="], + + "cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU="], + + "cli-table3": ["cli-table3@0.4.0", "", { "dependencies": { "kind-of": "^3.0.4", "object-assign": "^4.1.0", "string-width": "^1.0.1" }, "optionalDependencies": { "colors": "^1.1.2" } }, "sha512-o0slI6EFJNI2aKE9jG1bVN6jXJG2vjzYsGhyd9RqRV/YiiEmzSwNNXb5qJmfLDSOdvfA6sUvdKVvi3p3Y1apxA=="], + + "cli-width": ["cli-width@2.2.0", "", {}, "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="], + + "cliui": ["cliui@3.2.0", "", { "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" } }, "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0="], + + "clone": ["clone@2.1.2", "", {}, "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="], + + "clone-buffer": ["clone-buffer@1.0.0", "", {}, "sha1-4+JbIHrE5wGvch4staFnksrD3Fg="], + + "clone-stats": ["clone-stats@1.0.0", "", {}, "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA="], + + "cloneable-readable": ["cloneable-readable@1.1.2", "", { "dependencies": { "inherits": "^2.0.1", "process-nextick-args": "^2.0.0", "readable-stream": "^2.3.5" } }, "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg=="], + + "co": ["co@4.6.0", "", {}, "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="], + + "code-point-at": ["code-point-at@1.1.0", "", {}, "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="], + + "collection-map": ["collection-map@1.0.0", "", { "dependencies": { "arr-map": "^2.0.2", "for-own": "^1.0.0", "make-iterator": "^1.0.0" } }, "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw="], + + "collection-visit": ["collection-visit@1.0.0", "", { "dependencies": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" } }, "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA="], + + "color-convert": ["color-convert@1.9.2", "", { "dependencies": { "color-name": "1.1.1" } }, "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg=="], + + "color-name": ["color-name@1.1.1", "", {}, "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok="], + + "color-support": ["color-support@1.1.3", "", {}, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], + + "colors": ["colors@1.3.2", "", {}, "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ=="], + + "combined-stream": ["combined-stream@1.0.6", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha1-cj599ugBrFYTETp+RFqbactjKBg="], + + "commander": ["commander@2.16.0", "", {}, "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew=="], + + "commitizen": ["commitizen@2.10.1", "", { "dependencies": { "cachedir": "^1.1.0", "chalk": "1.1.3", "cz-conventional-changelog": "2.0.0", "dedent": "0.6.0", "detect-indent": "4.0.0", "find-node-modules": "1.0.4", "find-root": "1.0.0", "fs-extra": "^1.0.0", "glob": "7.1.1", "inquirer": "1.2.3", "lodash": "4.17.5", "minimist": "1.2.0", "opencollective": "1.0.3", "path-exists": "2.1.0", "shelljs": "0.7.6", "strip-json-comments": "2.0.1" } }, "sha1-jDld7zSolfTpSVLC78PJ60w2g70="], + + "commondir": ["commondir@1.0.1", "", {}, "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="], + + "compare-versions": ["compare-versions@3.3.0", "", {}, "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ=="], + + "component-emitter": ["component-emitter@1.2.1", "", {}, "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="], + + "concat-stream": ["concat-stream@1.6.2", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw=="], + + "console-browserify": ["console-browserify@1.1.0", "", { "dependencies": { "date-now": "^0.1.4" } }, "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA="], + + "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="], + + "constants-browserify": ["constants-browserify@1.0.0", "", {}, "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="], + + "conventional-commit-types": ["conventional-commit-types@2.2.0", "", {}, "sha1-XblXOdbCEqy+e29lahG5QLqmiUY="], + + "convert-source-map": ["convert-source-map@1.5.1", "", {}, "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU="], + + "copy-descriptor": ["copy-descriptor@0.1.1", "", {}, "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="], + + "copy-props": ["copy-props@2.0.4", "", { "dependencies": { "each-props": "^1.3.0", "is-plain-object": "^2.0.1" } }, "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A=="], + + "core-js": ["core-js@2.5.7", "", {}, "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="], + + "core-util-is": ["core-util-is@1.0.2", "", {}, "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="], + + "create-ecdh": ["create-ecdh@4.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" } }, "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw=="], + + "create-hash": ["create-hash@1.2.0", "", { "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", "md5.js": "^1.3.4", "ripemd160": "^2.0.1", "sha.js": "^2.4.0" } }, "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg=="], + + "create-hmac": ["create-hmac@1.1.7", "", { "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", "inherits": "^2.0.1", "ripemd160": "^2.0.0", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" } }, "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg=="], + + "cross-spawn": ["cross-spawn@5.1.0", "", { "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk="], + + "crypto-browserify": ["crypto-browserify@3.12.0", "", { "dependencies": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", "create-ecdh": "^4.0.0", "create-hash": "^1.1.0", "create-hmac": "^1.1.0", "diffie-hellman": "^5.0.0", "inherits": "^2.0.1", "pbkdf2": "^3.0.3", "public-encrypt": "^4.0.0", "randombytes": "^2.0.0", "randomfill": "^1.0.3" } }, "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg=="], + + "css": ["css@2.2.3", "", { "dependencies": { "inherits": "^2.0.1", "source-map": "^0.1.38", "source-map-resolve": "^0.5.1", "urix": "^0.1.0" } }, "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ=="], + + "cssom": ["cssom@0.3.4", "", {}, "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog=="], + + "cssstyle": ["cssstyle@1.0.0", "", { "dependencies": { "cssom": "0.3.x" } }, "sha512-Bpuh47j2mRMY60X90mXaJAEtJwxvA2roZzbgwAXYhMbmwmakdRr4Cq9L5SkleKJNLOKqHIa2YWyOXDX3VgggSQ=="], + + "currently-unhandled": ["currently-unhandled@0.4.1", "", { "dependencies": { "array-find-index": "^1.0.1" } }, "sha1-mI3zP+qxke95mmE2nddsF635V+o="], + + "cz-conventional-changelog": ["cz-conventional-changelog@2.1.0", "", { "dependencies": { "conventional-commit-types": "^2.0.0", "lodash.map": "^4.5.1", "longest": "^1.0.1", "right-pad": "^1.0.1", "word-wrap": "^1.0.3" } }, "sha1-L0vHOQ4yROTfKT5ro1Hkx0Cnx2Q="], + + "d": ["d@1.0.0", "", { "dependencies": { "es5-ext": "^0.10.9" } }, "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8="], + + "damerau-levenshtein": ["damerau-levenshtein@1.0.4", "", {}, "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ="], + + "dashdash": ["dashdash@1.14.1", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA="], + + "data-urls": ["data-urls@1.0.0", "", { "dependencies": { "abab": "^1.0.4", "whatwg-mimetype": "^2.0.0", "whatwg-url": "^6.4.0" } }, "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA=="], + + "date-fns": ["date-fns@1.29.0", "", {}, "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw=="], + + "date-now": ["date-now@0.1.4", "", {}, "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="], + + "death": ["death@1.1.0", "", {}, "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg="], + + "debug": ["debug@3.1.0", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g=="], + + "debug-fabulous": ["debug-fabulous@1.1.0", "", { "dependencies": { "debug": "3.X", "memoizee": "0.4.X", "object-assign": "4.X" } }, "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg=="], + + "decamelize": ["decamelize@1.2.0", "", {}, "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="], + + "decode-uri-component": ["decode-uri-component@0.2.0", "", {}, "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="], + + "dedent": ["dedent@0.6.0", "", {}, "sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s="], + + "deep-equal": ["deep-equal@1.0.1", "", {}, "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="], + + "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], + + "deep-is": ["deep-is@0.1.3", "", {}, "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="], + + "default-compare": ["default-compare@1.0.0", "", { "dependencies": { "kind-of": "^5.0.2" } }, "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ=="], + + "default-require-extensions": ["default-require-extensions@2.0.0", "", { "dependencies": { "strip-bom": "^3.0.0" } }, "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc="], + + "default-resolution": ["default-resolution@2.0.0", "", {}, "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ="], + + "define-properties": ["define-properties@1.1.2", "", { "dependencies": { "foreach": "^2.0.5", "object-keys": "^1.0.8" } }, "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ="], + + "define-property": ["define-property@2.0.2", "", { "dependencies": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" } }, "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ=="], + + "del": ["del@2.2.2", "", { "dependencies": { "globby": "^5.0.0", "is-path-cwd": "^1.0.0", "is-path-in-cwd": "^1.0.0", "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "rimraf": "^2.2.8" } }, "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="], + + "delegates": ["delegates@1.0.0", "", {}, "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="], + + "des.js": ["des.js@1.0.0", "", { "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw="], + + "detect-file": ["detect-file@0.1.0", "", { "dependencies": { "fs-exists-sync": "^0.1.0" } }, "sha1-STXe39lIhkjgBrASlWbpOGcR6mM="], + + "detect-indent": ["detect-indent@5.0.0", "", {}, "sha1-OHHMCmoALow+Wzz38zYmRnXwa50="], + + "detect-libc": ["detect-libc@1.0.3", "", {}, "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="], + + "detect-newline": ["detect-newline@2.1.0", "", {}, "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I="], + + "diff": ["diff@3.5.0", "", {}, "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="], + + "diffie-hellman": ["diffie-hellman@5.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" } }, "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg=="], + + "dnscache": ["dnscache@1.0.1", "", { "dependencies": { "asap": "~2.0.3", "lodash.clone": "~4.3.2" } }, "sha1-Qssrm/tej736OVqsdOEn/AUHTTE="], + + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + + "domain-browser": ["domain-browser@1.2.0", "", {}, "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="], + + "domexception": ["domexception@1.0.1", "", { "dependencies": { "webidl-conversions": "^4.0.2" } }, "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug=="], + + "duplexify": ["duplexify@3.6.0", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ=="], + + "each-props": ["each-props@1.3.2", "", { "dependencies": { "is-plain-object": "^2.0.1", "object.defaults": "^1.1.0" } }, "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA=="], + + "ecc-jsbn": ["ecc-jsbn@0.1.2", "", { "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk="], + + "ejs": ["ejs@2.6.1", "", {}, "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ=="], + + "electron-to-chromium": ["electron-to-chromium@1.3.55", "", {}, "sha1-8VDhCyC3fZ1Br8yjEu/gw7Gn/c4="], + + "elliptic": ["elliptic@6.4.0", "", { "dependencies": { "bn.js": "^4.4.0", "brorand": "^1.0.1", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" } }, "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8="], + + "emoji-regex": ["emoji-regex@6.5.1", "", {}, "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ=="], + + "emojis-list": ["emojis-list@2.1.0", "", {}, "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="], + + "encoding": ["encoding@0.1.12", "", { "dependencies": { "iconv-lite": "~0.4.13" } }, "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s="], + + "end-of-stream": ["end-of-stream@1.4.1", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q=="], + + "enhanced-resolve": ["enhanced-resolve@3.4.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "memory-fs": "^0.4.0", "object-assign": "^4.0.1", "tapable": "^0.2.7" } }, "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24="], + + "errno": ["errno@0.1.7", "", { "dependencies": { "prr": "~1.0.1" } }, "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg=="], + + "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], + + "es-abstract": ["es-abstract@1.12.0", "", { "dependencies": { "es-to-primitive": "^1.1.1", "function-bind": "^1.1.1", "has": "^1.0.1", "is-callable": "^1.1.3", "is-regex": "^1.0.4" } }, "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA=="], + + "es-to-primitive": ["es-to-primitive@1.1.1", "", { "dependencies": { "is-callable": "^1.1.1", "is-date-object": "^1.0.1", "is-symbol": "^1.0.1" } }, "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0="], + + "es5-ext": ["es5-ext@0.10.45", "", { "dependencies": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", "next-tick": "1" } }, "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ=="], + + "es6-iterator": ["es6-iterator@2.0.3", "", { "dependencies": { "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" } }, "sha1-p96IkUGgWpSwhUQDstCg+/qY87c="], + + "es6-symbol": ["es6-symbol@3.1.1", "", { "dependencies": { "d": "1", "es5-ext": "~0.10.14" } }, "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc="], + + "es6-weak-map": ["es6-weak-map@2.0.2", "", { "dependencies": { "d": "1", "es5-ext": "^0.10.14", "es6-iterator": "^2.0.1", "es6-symbol": "^3.1.1" } }, "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8="], + + "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="], + + "escodegen": ["escodegen@1.11.0", "", { "dependencies": { "esprima": "^3.1.3", "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1" }, "optionalDependencies": { "source-map": "~0.6.1" } }, "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw=="], + + "eslint": ["eslint@4.3.0", "", { "dependencies": { "ajv": "^5.2.0", "babel-code-frame": "^6.22.0", "chalk": "^1.1.3", "concat-stream": "^1.6.0", "cross-spawn": "^5.1.0", "debug": "^2.6.8", "doctrine": "^2.0.0", "eslint-scope": "^3.7.1", "espree": "^3.4.3", "esquery": "^1.0.0", "estraverse": "^4.2.0", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", "globals": "^9.17.0", "ignore": "^3.3.3", "imurmurhash": "^0.1.4", "inquirer": "^3.0.6", "is-resolvable": "^1.0.0", "js-yaml": "^3.8.4", "json-stable-stringify": "^1.0.1", "levn": "^0.3.0", "lodash": "^4.17.4", "minimatch": "^3.0.2", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", "pluralize": "^4.0.0", "progress": "^2.0.0", "require-uncached": "^1.0.3", "semver": "^5.3.0", "strip-json-comments": "~2.0.1", "table": "^4.0.1", "text-table": "~0.2.0" } }, "sha1-/NfJY3a780yF7mftABKimWQrEI8="], + + "eslint-config-fb-strict": ["eslint-config-fb-strict@22.4.3", "", { "dependencies": { "eslint-config-fbjs": "^2.0.1" } }, "sha512-xGH75nMO69RqDU96KCI/wh58Y3Ej+xLl/zdK5uQKfvf2DRcwRw1JgArCR+9P0SzWIgEzPPEGVxpRPjYW3XfI+w=="], + + "eslint-config-fbjs": ["eslint-config-fbjs@2.0.1", "", {}, "sha512-nZ/JByixNK/8epeQqmrtNCYYMXCjHoPkJwHaHg4aZyZlS62YLttDSWYE6ISGl070V+o6dkFbDALceWaO3Po+Sw=="], + + "eslint-plugin-babel": ["eslint-plugin-babel@5.1.0", "", { "dependencies": { "eslint-rule-composer": "^0.3.0" } }, "sha512-HBkv9Q0LU/IhNUauC8TrbhcN79Yq/+xh2bYTOcv6KMaV2tsvVphkHwDTJ9r3C6mJUnmxrtzT3DQfrWj0rOISqQ=="], + + "eslint-plugin-flowtype": ["eslint-plugin-flowtype@2.50.0", "", { "dependencies": { "lodash": "^4.17.10" } }, "sha512-10FnBXCp8odYcpUFXGAh+Zko7py0hUWutTd3BN/R9riukH360qNPLYPR3/xV9eu9K7OJDjJrsflBnL6RwxFnlw=="], + + "eslint-plugin-jasmine": ["eslint-plugin-jasmine@2.10.1", "", {}, "sha1-VzO3CedR9LxA4x4cFpib0s377Jc="], + + "eslint-plugin-jest": ["eslint-plugin-jest@21.18.0", "", {}, "sha512-fhuJuehoMtuEQ3Klgx0629hDmbs0M0g4tSZ65Wq2NqpLWCK5UC7hQnGS1Wh4+Vc/9P4ss4HxqZ1XK7honqUZNg=="], + + "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.1.1", "", { "dependencies": { "aria-query": "^3.0.0", "array-includes": "^3.0.3", "ast-types-flow": "^0.0.7", "axobject-query": "^2.0.1", "damerau-levenshtein": "^1.0.4", "emoji-regex": "^6.5.1", "has": "^1.0.3", "jsx-ast-utils": "^2.0.1" } }, "sha512-JsxNKqa3TwmPypeXNnI75FntkUktGzI1wSa1LgNZdSOMI+B4sxnr1lSF8m8lPiz4mKiC+14ysZQM4scewUrP7A=="], + + "eslint-plugin-prefer-object-spread": ["eslint-plugin-prefer-object-spread@1.2.1", "", {}, "sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw="], + + "eslint-plugin-prettier": ["eslint-plugin-prettier@2.6.2", "", { "dependencies": { "fast-diff": "^1.1.1", "jest-docblock": "^21.0.0" } }, "sha512-tGek5clmW5swrAx1mdPYM8oThrBE83ePh7LeseZHBWfHVGrHPhKn7Y5zgRMbU/9D5Td9K4CEmUPjGxA7iw98Og=="], + + "eslint-plugin-react": ["eslint-plugin-react@7.10.0", "", { "dependencies": { "doctrine": "^2.1.0", "has": "^1.0.3", "jsx-ast-utils": "^2.0.1", "prop-types": "^15.6.2" } }, "sha512-18rzWn4AtbSUxFKKM7aCVcj5LXOhOKdwBino3KKWy4psxfPW0YtIbE8WNRDUdyHFL50BeLb6qFd4vpvNYyp7hw=="], + + "eslint-plugin-relay": ["eslint-plugin-relay@0.0.28", "", { "dependencies": { "graphql": "^14.0.0" } }, "sha512-CvyT/WxEQmcUKE4lVqjxgioTj3zSvHnT9bvR4cISgs9j2z4J5Ojsurjcv/kWe4I6gf6L+lV6zcVuZ2LkiRIO6g=="], + + "eslint-plugin-yarn-internal": ["eslint-plugin-yarn-internal@file:scripts/eslint-rules", {}], + + "eslint-rule-composer": ["eslint-rule-composer@0.3.0", "", {}, "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg=="], + + "eslint-scope": ["eslint-scope@3.7.3", "", { "dependencies": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA=="], + + "espree": ["espree@3.5.4", "", { "dependencies": { "acorn": "^5.5.0", "acorn-jsx": "^3.0.0" } }, "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A=="], + + "esprima": ["esprima@4.0.1", "", {}, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esquery": ["esquery@1.0.1", "", { "dependencies": { "estraverse": "^4.0.0" } }, "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA=="], + + "esrecurse": ["esrecurse@4.2.1", "", { "dependencies": { "estraverse": "^4.1.0" } }, "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ=="], + + "estraverse": ["estraverse@4.2.0", "", {}, "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="], + + "esutils": ["esutils@2.0.2", "", {}, "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="], + + "event-emitter": ["event-emitter@0.3.5", "", { "dependencies": { "d": "1", "es5-ext": "~0.10.14" } }, "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk="], + + "events": ["events@1.1.1", "", {}, "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="], + + "evp_bytestokey": ["evp_bytestokey@1.0.3", "", { "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" } }, "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA=="], + + "exec-sh": ["exec-sh@0.2.2", "", { "dependencies": { "merge": "^1.2.0" } }, "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw=="], + + "execa": ["execa@0.11.0", "", { "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha512-k5AR22vCt1DcfeiRixW46U5tMLtBg44ssdJM9PiXw3D8Bn5qyxFCSnKY/eR22y+ctFDGPqafpaXg2G4Emyua4A=="], + + "exit": ["exit@0.1.2", "", {}, "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="], + + "exit-hook": ["exit-hook@1.1.1", "", {}, "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g="], + + "expand-brackets": ["expand-brackets@0.1.5", "", { "dependencies": { "is-posix-bracket": "^0.1.0" } }, "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s="], + + "expand-range": ["expand-range@1.8.2", "", { "dependencies": { "fill-range": "^2.1.0" } }, "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc="], + + "expand-tilde": ["expand-tilde@1.2.2", "", { "dependencies": { "os-homedir": "^1.0.1" } }, "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk="], + + "expect": ["expect@22.4.3", "", { "dependencies": { "ansi-styles": "^3.2.0", "jest-diff": "^22.4.3", "jest-get-type": "^22.4.3", "jest-matcher-utils": "^22.4.3", "jest-message-util": "^22.4.3", "jest-regex-util": "^22.4.3" } }, "sha512-XcNXEPehqn8b/jm8FYotdX0YrXn36qp4HWlrVT4ktwQas1l1LPxiVWncYnnL2eyMtKAmVIaG0XAp0QlrqJaxaA=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "extend-shallow": ["extend-shallow@3.0.2", "", { "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" } }, "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg="], + + "external-editor": ["external-editor@3.0.3", "", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA=="], + + "extglob": ["extglob@0.3.2", "", { "dependencies": { "is-extglob": "^1.0.0" } }, "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE="], + + "extsprintf": ["extsprintf@1.3.0", "", {}, "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="], + + "fancy-log": ["fancy-log@1.3.2", "", { "dependencies": { "ansi-gray": "^0.1.1", "color-support": "^1.1.3", "time-stamp": "^1.0.0" } }, "sha1-9BEl49hPLn2JpD0G2VjI94vha+E="], + + "fast-deep-equal": ["fast-deep-equal@1.1.0", "", {}, "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="], + + "fast-diff": ["fast-diff@1.1.2", "", {}, "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.0.0", "", {}, "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="], + + "fb-watchman": ["fb-watchman@2.0.0", "", { "dependencies": { "bser": "^2.0.0" } }, "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg="], + + "figures": ["figures@2.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI="], + + "file-entry-cache": ["file-entry-cache@2.0.0", "", { "dependencies": { "flat-cache": "^1.2.1", "object-assign": "^4.0.1" } }, "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E="], + + "filename-regex": ["filename-regex@2.0.1", "", {}, "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="], + + "filepaths": ["filepaths@0.3.0", "", {}, "sha1-ocmkYBturn+4dvwayYR5zrVXwXc="], + + "fileset": ["fileset@2.0.3", "", { "dependencies": { "glob": "^7.0.3", "minimatch": "^3.0.3" } }, "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA="], + + "fill-range": ["fill-range@2.2.4", "", { "dependencies": { "is-number": "^2.1.0", "isobject": "^2.0.0", "randomatic": "^3.0.0", "repeat-element": "^1.1.2", "repeat-string": "^1.5.2" } }, "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q=="], + + "find-cache-dir": ["find-cache-dir@0.1.1", "", { "dependencies": { "commondir": "^1.0.1", "mkdirp": "^0.5.1", "pkg-dir": "^1.0.0" } }, "sha1-yN765XyKUqinhPnjHFfHQumToLk="], + + "find-node-modules": ["find-node-modules@1.0.4", "", { "dependencies": { "findup-sync": "0.4.2", "merge": "^1.2.0" } }, "sha1-tt6zzMtpnIcDdne87eLF9YYrJVA="], + + "find-root": ["find-root@1.0.0", "", {}, "sha1-li/yEaqyXGUg/u641ih/j26VgHo="], + + "find-up": ["find-up@1.1.2", "", { "dependencies": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" } }, "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8="], + + "findup-sync": ["findup-sync@0.4.2", "", { "dependencies": { "detect-file": "^0.1.0", "is-glob": "^2.0.1", "micromatch": "^2.3.7", "resolve-dir": "^0.1.0" } }, "sha1-qBF9D3MST1pFRoOVef5S1xKfteU="], + + "fined": ["fined@1.1.0", "", { "dependencies": { "expand-tilde": "^2.0.2", "is-plain-object": "^2.0.3", "object.defaults": "^1.1.0", "object.pick": "^1.2.0", "parse-filepath": "^1.0.1" } }, "sha1-s33IRLdqL15wgeiE98CuNE8VNHY="], + + "flagged-respawn": ["flagged-respawn@1.0.0", "", {}, "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c="], + + "flat-cache": ["flat-cache@1.3.0", "", { "dependencies": { "circular-json": "^0.3.1", "del": "^2.0.2", "graceful-fs": "^4.1.2", "write": "^0.2.1" } }, "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE="], + + "flow-bin": ["flow-bin@0.66.0", "", {}, "sha1-qW3ecBXcM0P9VSp7SWPAK+cFyiY="], + + "flush-write-stream": ["flush-write-stream@1.0.3", "", { "dependencies": { "inherits": "^2.0.1", "readable-stream": "^2.0.4" } }, "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw=="], + + "for-in": ["for-in@1.0.2", "", {}, "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="], + + "for-own": ["for-own@0.1.5", "", { "dependencies": { "for-in": "^1.0.1" } }, "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4="], + + "foreach": ["foreach@2.0.5", "", {}, "sha1-C+4AUBiusmDQo6865ljdATbsG5k="], + + "forever-agent": ["forever-agent@0.6.1", "", {}, "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="], + + "fork-stream": ["fork-stream@0.0.4", "", {}, "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA="], + + "form-data": ["form-data@2.3.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "1.0.6", "mime-types": "^2.1.12" } }, "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk="], + + "fragment-cache": ["fragment-cache@0.2.1", "", { "dependencies": { "map-cache": "^0.2.2" } }, "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk="], + + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + + "fs-exists-sync": ["fs-exists-sync@0.1.0", "", {}, "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0="], + + "fs-extra": ["fs-extra@1.0.0", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^2.1.0", "klaw": "^1.0.0" } }, "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA="], + + "fs-minipass": ["fs-minipass@1.2.5", "", { "dependencies": { "minipass": "^2.2.1" } }, "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ=="], + + "fs-mkdirp-stream": ["fs-mkdirp-stream@1.0.0", "", { "dependencies": { "graceful-fs": "^4.1.11", "through2": "^2.0.3" } }, "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="], + + "fsevents": ["fsevents@1.2.4", "", { "dependencies": { "nan": "^2.9.2", "node-pre-gyp": "^0.10.0" } }, "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg=="], + + "function-bind": ["function-bind@1.1.1", "", {}, "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="], + + "functional-red-black-tree": ["functional-red-black-tree@1.0.1", "", {}, "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="], + + "gauge": ["gauge@2.7.4", "", { "dependencies": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", "object-assign": "^4.1.0", "signal-exit": "^3.0.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" } }, "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c="], + + "get-caller-file": ["get-caller-file@1.0.3", "", {}, "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="], + + "get-stdin": ["get-stdin@4.0.1", "", {}, "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="], + + "get-stream": ["get-stream@4.0.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-FneLKMENeOR7wOK0/ZXCh+lwqtnPwkeunJjRN28LPqzGvNAhYvrTAhXv6xDm4vsJ0M7lcRbIYHQudKsSy2RtSQ=="], + + "get-value": ["get-value@2.0.6", "", {}, "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="], + + "getpass": ["getpass@0.1.7", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo="], + + "git-release-notes": ["git-release-notes@3.0.0", "", { "dependencies": { "date-fns": "^1.29.0", "debug": "^3.1.0", "ejs": "^2.5.7", "optimist": "^0.6.1" } }, "sha512-FvaIV55dE03hXmD+yUB3ZLyxoiDQZetYw53hX7EPOfr3u+caIIXyUiGilJB+4fF7IjglE4YBY8O4gl3wsviFQA=="], + + "glob": ["glob@7.1.2", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ=="], + + "glob-base": ["glob-base@0.3.0", "", { "dependencies": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" } }, "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q="], + + "glob-parent": ["glob-parent@3.1.0", "", { "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" } }, "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4="], + + "glob-stream": ["glob-stream@6.1.0", "", { "dependencies": { "extend": "^3.0.0", "glob": "^7.1.1", "glob-parent": "^3.1.0", "is-negated-glob": "^1.0.0", "ordered-read-streams": "^1.0.0", "pumpify": "^1.3.5", "readable-stream": "^2.1.5", "remove-trailing-separator": "^1.0.1", "to-absolute-glob": "^2.0.0", "unique-stream": "^2.0.2" } }, "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ="], + + "glob-watcher": ["glob-watcher@5.0.1", "", { "dependencies": { "async-done": "^1.2.0", "chokidar": "^2.0.0", "just-debounce": "^1.0.0", "object.defaults": "^1.1.0" } }, "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g=="], + + "global-modules": ["global-modules@0.2.3", "", { "dependencies": { "global-prefix": "^0.1.4", "is-windows": "^0.2.0" } }, "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0="], + + "global-prefix": ["global-prefix@0.1.5", "", { "dependencies": { "homedir-polyfill": "^1.0.0", "ini": "^1.3.4", "is-windows": "^0.2.0", "which": "^1.2.12" } }, "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948="], + + "globals": ["globals@9.18.0", "", {}, "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="], + + "globby": ["globby@5.0.0", "", { "dependencies": { "array-union": "^1.0.1", "arrify": "^1.0.0", "glob": "^7.0.3", "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" } }, "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0="], + + "glogg": ["glogg@1.0.1", "", { "dependencies": { "sparkles": "^1.0.0" } }, "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw=="], + + "graceful-fs": ["graceful-fs@4.1.11", "", {}, "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="], + + "graphql": ["graphql@14.0.2", "", { "dependencies": { "iterall": "^1.2.2" } }, "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw=="], + + "growly": ["growly@1.3.0", "", {}, "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE="], + + "gulp": ["gulp@4.0.0", "", { "dependencies": { "glob-watcher": "^5.0.0", "gulp-cli": "^2.0.0", "undertaker": "^1.0.0", "vinyl-fs": "^3.0.0" } }, "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y="], + + "gulp-babel": ["gulp-babel@7.0.1", "", { "dependencies": { "plugin-error": "^1.0.1", "replace-ext": "0.0.1", "through2": "^2.0.0", "vinyl-sourcemaps-apply": "^0.2.0" } }, "sha512-UqHS3AdxZyJCRxqnAX603Dj3k/Wx6hzcgmav3QcxvsIFq3Y8ZkU7iXd0O+JwD5ivqCc6o0r1S7tCB/xxLnuSNw=="], + + "gulp-cli": ["gulp-cli@2.0.1", "", { "dependencies": { "ansi-colors": "^1.0.1", "archy": "^1.0.0", "array-sort": "^1.0.0", "color-support": "^1.1.3", "concat-stream": "^1.6.0", "copy-props": "^2.0.1", "fancy-log": "^1.3.2", "gulplog": "^1.0.0", "interpret": "^1.1.0", "isobject": "^3.0.1", "liftoff": "^2.5.0", "matchdep": "^2.0.0", "mute-stdout": "^1.0.0", "pretty-hrtime": "^1.0.0", "replace-homedir": "^1.0.0", "semver-greatest-satisfied-range": "^1.1.0", "v8flags": "^3.0.1", "yargs": "^7.1.0" } }, "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ=="], + + "gulp-if": ["gulp-if@2.0.2", "", { "dependencies": { "gulp-match": "^1.0.3", "ternary-stream": "^2.0.1", "through2": "^2.0.1" } }, "sha1-pJe351cwBQQcqivIt92jyARE1ik="], + + "gulp-match": ["gulp-match@1.0.3", "", { "dependencies": { "minimatch": "^3.0.3" } }, "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4="], + + "gulp-newer": ["gulp-newer@1.4.0", "", { "dependencies": { "glob": "^7.0.3", "kew": "^0.7.0", "plugin-error": "^0.1.2" } }, "sha512-h79fGO55S/P9eAADbLAP9aTtVYpLSR1ONj08VPaSdVVNVYhTS8p1CO1TW7kEMu+hC+sytmCqcUr5LesvZEtDoQ=="], + + "gulp-plumber": ["gulp-plumber@1.2.0", "", { "dependencies": { "chalk": "^1.1.3", "fancy-log": "^1.3.2", "plugin-error": "^0.1.2", "through2": "^2.0.3" } }, "sha512-L/LJftsbKoHbVj6dN5pvMsyJn9jYI0wT0nMg3G6VZhDac4NesezecYTi8/48rHi+yEic3sUpw6jlSc7qNWh32A=="], + + "gulp-sourcemaps": ["gulp-sourcemaps@2.6.4", "", { "dependencies": { "@gulp-sourcemaps/identity-map": "1.X", "@gulp-sourcemaps/map-sources": "1.X", "acorn": "5.X", "convert-source-map": "1.X", "css": "2.X", "debug-fabulous": "1.X", "detect-newline": "2.X", "graceful-fs": "4.X", "source-map": "~0.6.0", "strip-bom-string": "1.X", "through2": "2.X" } }, "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo="], + + "gulplog": ["gulplog@1.0.0", "", { "dependencies": { "glogg": "^1.0.0" } }, "sha1-4oxNRdBey77YGDY86PnFkmIp/+U="], + + "gunzip-maybe": ["gunzip-maybe@1.4.1", "", { "dependencies": { "browserify-zlib": "^0.1.4", "is-deflate": "^1.0.0", "is-gzip": "^1.0.0", "peek-stream": "^1.1.0", "pumpify": "^1.3.3", "through2": "^2.0.3" } }, "sha512-qtutIKMthNJJgeHQS7kZ9FqDq59/Wn0G2HYCRNjpup7yKfVI6/eqwpmroyZGFoCYaG+sW6psNVb4zoLADHpp2g=="], + + "handlebars": ["handlebars@4.0.11", "", { "dependencies": { "async": "^1.4.0", "optimist": "^0.6.1", "source-map": "^0.4.4" }, "optionalDependencies": { "uglify-js": "^2.6" } }, "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw="], + + "har-schema": ["har-schema@2.0.0", "", {}, "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="], + + "har-validator": ["har-validator@5.0.3", "", { "dependencies": { "ajv": "^5.1.0", "har-schema": "^2.0.0" } }, "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0="], + + "has": ["has@1.0.3", "", { "dependencies": { "function-bind": "^1.1.1" } }, "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw=="], + + "has-ansi": ["has-ansi@2.0.0", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE="], + + "has-flag": ["has-flag@1.0.0", "", {}, "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo="], + + "has-symbols": ["has-symbols@1.0.0", "", {}, "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="], + + "has-unicode": ["has-unicode@2.0.1", "", {}, "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="], + + "has-value": ["has-value@1.0.0", "", { "dependencies": { "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" } }, "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc="], + + "has-values": ["has-values@1.0.0", "", { "dependencies": { "is-number": "^3.0.0", "kind-of": "^4.0.0" } }, "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8="], + + "hash-base": ["hash-base@3.0.4", "", { "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg="], + + "hash-for-dep": ["hash-for-dep@1.2.3", "", { "dependencies": { "broccoli-kitchen-sink-helpers": "^0.3.1", "heimdalljs": "^0.2.3", "heimdalljs-logger": "^0.1.7", "resolve": "^1.4.0" } }, "sha512-NE//rDaCFpWHViw30YM78OAGBShU+g4dnUGY3UWGyEzPOGYg/ptOjk32nEc+bC1xz+RfK5UIs6lOL6eQdrV4Ow=="], + + "hash.js": ["hash.js@1.1.5", "", { "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA=="], + + "heimdalljs": ["heimdalljs@0.2.5", "", { "dependencies": { "rsvp": "~3.2.1" } }, "sha1-aqVDCO7nk7ZCz/nPlHgURfN3MKw="], + + "heimdalljs-logger": ["heimdalljs-logger@0.1.9", "", { "dependencies": { "debug": "^2.2.0", "heimdalljs": "^0.2.0" } }, "sha1-12raTkW3u294b8nAEKaOsuL68XY="], + + "hmac-drbg": ["hmac-drbg@1.0.1", "", { "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.1" } }, "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE="], + + "home-or-tmp": ["home-or-tmp@2.0.0", "", { "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.1" } }, "sha1-42w/LSyufXRqhX440Y1fMqeILbg="], + + "homedir-polyfill": ["homedir-polyfill@1.0.1", "", { "dependencies": { "parse-passwd": "^1.0.0" } }, "sha1-TCu8inWJmP7r9e1oWA921GdotLw="], + + "hosted-git-info": ["hosted-git-info@2.7.1", "", {}, "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="], + + "html-encoding-sniffer": ["html-encoding-sniffer@1.0.2", "", { "dependencies": { "whatwg-encoding": "^1.0.1" } }, "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw=="], + + "http-signature": ["http-signature@1.2.0", "", { "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE="], + + "https-browserify": ["https-browserify@1.0.0", "", {}, "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "ieee754": ["ieee754@1.1.12", "", {}, "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA=="], + + "ignore": ["ignore@3.3.10", "", {}, "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="], + + "ignore-walk": ["ignore-walk@3.0.1", "", { "dependencies": { "minimatch": "^3.0.4" } }, "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ=="], + + "import-local": ["import-local@1.0.0", "", { "dependencies": { "pkg-dir": "^2.0.0", "resolve-cwd": "^2.0.0" } }, "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ=="], + + "imports-loader": ["imports-loader@0.8.0", "", { "dependencies": { "loader-utils": "^1.0.2", "source-map": "^0.6.1" } }, "sha512-kXWL7Scp8KQ4552ZcdVTeaQCZSLW+e6nJfp3cwUMB673T7Hr98Xjx5JK+ql7ADlJUvj1JS5O01RLbKoutN5QDQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha1-khi5srkoojixPcT7a21XbyMUU+o="], + + "indexof": ["indexof@0.0.1", "", {}, "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk="], + + "inherits": ["inherits@2.0.3", "", {}, "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="], + + "ini": ["ini@1.3.5", "", {}, "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="], + + "inquirer": ["inquirer@6.2.0", "", { "dependencies": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.0", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.0", "figures": "^2.0.0", "lodash": "^4.17.10", "mute-stream": "0.0.7", "run-async": "^2.2.0", "rxjs": "^6.1.0", "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" } }, "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg=="], + + "interpret": ["interpret@1.1.0", "", {}, "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ="], + + "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], + + "invert-kv": ["invert-kv@1.0.0", "", {}, "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="], + + "is-absolute": ["is-absolute@1.0.0", "", { "dependencies": { "is-relative": "^1.0.0", "is-windows": "^1.0.1" } }, "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA=="], + + "is-accessor-descriptor": ["is-accessor-descriptor@1.0.0", "", { "dependencies": { "kind-of": "^6.0.0" } }, "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ=="], + + "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="], + + "is-binary-path": ["is-binary-path@1.0.1", "", { "dependencies": { "binary-extensions": "^1.0.0" } }, "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg="], + + "is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="], + + "is-builtin-module": ["is-builtin-module@2.0.0", "", { "dependencies": { "builtin-modules": "^2.0.0" } }, "sha512-G2jLHphOywpgrL/AaJKWDXpdpGR9X4V1PCkB+EwG5Z28z8EukgdWnAUFAS2wdBtIpwHhHBIiq0NBOWEbSXN0Rg=="], + + "is-callable": ["is-callable@1.1.4", "", {}, "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="], + + "is-ci": ["is-ci@1.1.0", "", { "dependencies": { "ci-info": "^1.0.0" } }, "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg=="], + + "is-data-descriptor": ["is-data-descriptor@1.0.0", "", { "dependencies": { "kind-of": "^6.0.0" } }, "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ=="], + + "is-date-object": ["is-date-object@1.0.1", "", {}, "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="], + + "is-deflate": ["is-deflate@1.0.0", "", {}, "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ="], + + "is-descriptor": ["is-descriptor@1.0.2", "", { "dependencies": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } }, "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg=="], + + "is-dotfile": ["is-dotfile@1.0.3", "", {}, "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="], + + "is-equal-shallow": ["is-equal-shallow@0.1.3", "", { "dependencies": { "is-primitive": "^2.0.0" } }, "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ="], + + "is-extendable": ["is-extendable@0.1.1", "", {}, "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="], + + "is-extglob": ["is-extglob@1.0.0", "", {}, "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="], + + "is-finite": ["is-finite@1.0.2", "", { "dependencies": { "number-is-nan": "^1.0.0" } }, "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@1.0.0", "", { "dependencies": { "number-is-nan": "^1.0.0" } }, "sha1-754xOG8DGn8NZDr4L95QxFfvAMs="], + + "is-generator-fn": ["is-generator-fn@1.0.0", "", {}, "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go="], + + "is-glob": ["is-glob@2.0.1", "", { "dependencies": { "is-extglob": "^1.0.0" } }, "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM="], + + "is-gzip": ["is-gzip@1.0.0", "", {}, "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM="], + + "is-negated-glob": ["is-negated-glob@1.0.0", "", {}, "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI="], + + "is-number": ["is-number@4.0.0", "", {}, "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ=="], + + "is-path-cwd": ["is-path-cwd@1.0.0", "", {}, "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0="], + + "is-path-in-cwd": ["is-path-in-cwd@1.0.1", "", { "dependencies": { "is-path-inside": "^1.0.0" } }, "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ=="], + + "is-path-inside": ["is-path-inside@1.0.1", "", { "dependencies": { "path-is-inside": "^1.0.1" } }, "sha1-jvW33lBDej/cprToZe96pVy0gDY="], + + "is-plain-obj": ["is-plain-obj@1.1.0", "", {}, "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="], + + "is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="], + + "is-posix-bracket": ["is-posix-bracket@0.1.1", "", {}, "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="], + + "is-primitive": ["is-primitive@2.0.0", "", {}, "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="], + + "is-promise": ["is-promise@2.1.0", "", {}, "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="], + + "is-regex": ["is-regex@1.0.4", "", { "dependencies": { "has": "^1.0.1" } }, "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE="], + + "is-relative": ["is-relative@1.0.0", "", { "dependencies": { "is-unc-path": "^1.0.0" } }, "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA=="], + + "is-resolvable": ["is-resolvable@1.1.0", "", {}, "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg=="], + + "is-stream": ["is-stream@1.1.0", "", {}, "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="], + + "is-symbol": ["is-symbol@1.0.1", "", {}, "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI="], + + "is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="], + + "is-unc-path": ["is-unc-path@1.0.0", "", { "dependencies": { "unc-path-regex": "^0.1.2" } }, "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ=="], + + "is-utf8": ["is-utf8@0.2.1", "", {}, "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="], + + "is-valid-glob": ["is-valid-glob@1.0.0", "", {}, "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao="], + + "is-webpack-bundle": ["is-webpack-bundle@1.0.0", "", {}, "sha1-V2pQu3xT0dalwWR5Ock64su5Duo="], + + "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], + + "isarray": ["isarray@1.0.0", "", {}, "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="], + + "isexe": ["isexe@2.0.0", "", {}, "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="], + + "isobject": ["isobject@3.0.1", "", {}, "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="], + + "isstream": ["isstream@0.1.2", "", {}, "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="], + + "istanbul-api": ["istanbul-api@1.3.1", "", { "dependencies": { "async": "^2.1.4", "compare-versions": "^3.1.0", "fileset": "^2.0.2", "istanbul-lib-coverage": "^1.2.0", "istanbul-lib-hook": "^1.2.0", "istanbul-lib-instrument": "^1.10.1", "istanbul-lib-report": "^1.1.4", "istanbul-lib-source-maps": "^1.2.4", "istanbul-reports": "^1.3.0", "js-yaml": "^3.7.0", "mkdirp": "^0.5.1", "once": "^1.4.0" } }, "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g=="], + + "istanbul-lib-coverage": ["istanbul-lib-coverage@1.2.0", "", {}, "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A=="], + + "istanbul-lib-hook": ["istanbul-lib-hook@1.2.1", "", { "dependencies": { "append-transform": "^1.0.0" } }, "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg=="], + + "istanbul-lib-instrument": ["istanbul-lib-instrument@1.10.1", "", { "dependencies": { "babel-generator": "^6.18.0", "babel-template": "^6.16.0", "babel-traverse": "^6.18.0", "babel-types": "^6.18.0", "babylon": "^6.18.0", "istanbul-lib-coverage": "^1.2.0", "semver": "^5.3.0" } }, "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ=="], + + "istanbul-lib-report": ["istanbul-lib-report@1.1.4", "", { "dependencies": { "istanbul-lib-coverage": "^1.2.0", "mkdirp": "^0.5.1", "path-parse": "^1.0.5", "supports-color": "^3.1.2" } }, "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA=="], + + "istanbul-lib-source-maps": ["istanbul-lib-source-maps@1.2.3", "", { "dependencies": { "debug": "^3.1.0", "istanbul-lib-coverage": "^1.1.2", "mkdirp": "^0.5.1", "rimraf": "^2.6.1", "source-map": "^0.5.3" } }, "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA=="], + + "istanbul-reports": ["istanbul-reports@1.3.0", "", { "dependencies": { "handlebars": "^4.0.3" } }, "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA=="], + + "iterall": ["iterall@1.2.2", "", {}, "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA=="], + + "jest": ["jest@22.4.4", "", { "dependencies": { "import-local": "^1.0.0", "jest-cli": "^22.4.4" } }, "sha512-eBhhW8OS/UuX3HxgzNBSVEVhSuRDh39Z1kdYkQVWna+scpgsrD7vSeBI7tmEvsguPDMnfJodW28YBnhv/BzSew=="], + + "jest-changed-files": ["jest-changed-files@22.4.3", "", { "dependencies": { "throat": "^4.0.0" } }, "sha512-83Dh0w1aSkUNFhy5d2dvqWxi/y6weDwVVLU6vmK0cV9VpRxPzhTeGimbsbRDSnEoszhF937M4sDLLeS7Cu/Tmw=="], + + "jest-cli": ["jest-cli@22.4.4", "", { "dependencies": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", "exit": "^0.1.2", "glob": "^7.1.2", "graceful-fs": "^4.1.11", "import-local": "^1.0.0", "is-ci": "^1.0.10", "istanbul-api": "^1.1.14", "istanbul-lib-coverage": "^1.1.1", "istanbul-lib-instrument": "^1.8.0", "istanbul-lib-source-maps": "^1.2.1", "jest-changed-files": "^22.2.0", "jest-config": "^22.4.4", "jest-environment-jsdom": "^22.4.1", "jest-get-type": "^22.1.0", "jest-haste-map": "^22.4.2", "jest-message-util": "^22.4.0", "jest-regex-util": "^22.1.0", "jest-resolve-dependencies": "^22.1.0", "jest-runner": "^22.4.4", "jest-runtime": "^22.4.4", "jest-snapshot": "^22.4.0", "jest-util": "^22.4.1", "jest-validate": "^22.4.4", "jest-worker": "^22.2.2", "micromatch": "^2.3.11", "node-notifier": "^5.2.1", "realpath-native": "^1.0.0", "rimraf": "^2.5.4", "slash": "^1.0.0", "string-length": "^2.0.0", "strip-ansi": "^4.0.0", "which": "^1.2.12", "yargs": "^10.0.3" } }, "sha512-I9dsgkeyjVEEZj9wrGrqlH+8OlNob9Iptyl+6L5+ToOLJmHm4JwOPatin1b2Bzp5R5YRQJ+oiedx7o1H7wJzhA=="], + + "jest-config": ["jest-config@22.4.4", "", { "dependencies": { "chalk": "^2.0.1", "glob": "^7.1.1", "jest-environment-jsdom": "^22.4.1", "jest-environment-node": "^22.4.1", "jest-get-type": "^22.1.0", "jest-jasmine2": "^22.4.4", "jest-regex-util": "^22.1.0", "jest-resolve": "^22.4.2", "jest-util": "^22.4.1", "jest-validate": "^22.4.4", "pretty-format": "^22.4.0" } }, "sha512-9CKfo1GC4zrXSoMLcNeDvQBfgtqGTB1uP8iDIZ97oB26RCUb886KkKWhVcpyxVDOUxbhN+uzcBCeFe7w+Iem4A=="], + + "jest-diff": ["jest-diff@22.4.3", "", { "dependencies": { "chalk": "^2.0.1", "diff": "^3.2.0", "jest-get-type": "^22.4.3", "pretty-format": "^22.4.3" } }, "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA=="], + + "jest-docblock": ["jest-docblock@21.2.0", "", {}, "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw=="], + + "jest-environment-jsdom": ["jest-environment-jsdom@22.4.3", "", { "dependencies": { "jest-mock": "^22.4.3", "jest-util": "^22.4.3", "jsdom": "^11.5.1" } }, "sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w=="], + + "jest-environment-node": ["jest-environment-node@22.4.3", "", { "dependencies": { "jest-mock": "^22.4.3", "jest-util": "^22.4.3" } }, "sha512-reZl8XF6t/lMEuPWwo9OLfttyC26A5AMgDyEQ6DBgZuyfyeNUzYT8BFo6uxCCP/Av/b7eb9fTi3sIHFPBzmlRA=="], + + "jest-get-type": ["jest-get-type@22.4.3", "", {}, "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w=="], + + "jest-haste-map": ["jest-haste-map@22.4.3", "", { "dependencies": { "fb-watchman": "^2.0.0", "graceful-fs": "^4.1.11", "jest-docblock": "^22.4.3", "jest-serializer": "^22.4.3", "jest-worker": "^22.4.3", "micromatch": "^2.3.11", "sane": "^2.0.0" } }, "sha512-4Q9fjzuPVwnaqGKDpIsCSoTSnG3cteyk2oNVjBX12HHOaF1oxql+uUiqZb5Ndu7g/vTZfdNwwy4WwYogLh29DQ=="], + + "jest-jasmine2": ["jest-jasmine2@22.4.4", "", { "dependencies": { "chalk": "^2.0.1", "co": "^4.6.0", "expect": "^22.4.0", "graceful-fs": "^4.1.11", "is-generator-fn": "^1.0.0", "jest-diff": "^22.4.0", "jest-matcher-utils": "^22.4.0", "jest-message-util": "^22.4.0", "jest-snapshot": "^22.4.0", "jest-util": "^22.4.1", "source-map-support": "^0.5.0" } }, "sha512-nK3vdUl50MuH7vj/8at7EQVjPGWCi3d5+6aCi7Gxy/XMWdOdbH1qtO/LjKbqD8+8dUAEH+BVVh7HkjpCWC1CSw=="], + + "jest-leak-detector": ["jest-leak-detector@22.4.3", "", { "dependencies": { "pretty-format": "^22.4.3" } }, "sha512-NZpR/Ls7+ndO57LuXROdgCGz2RmUdC541tTImL9bdUtU3WadgFGm0yV+Ok4Fuia/1rLAn5KaJ+i76L6e3zGJYQ=="], + + "jest-matcher-utils": ["jest-matcher-utils@22.4.3", "", { "dependencies": { "chalk": "^2.0.1", "jest-get-type": "^22.4.3", "pretty-format": "^22.4.3" } }, "sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA=="], + + "jest-message-util": ["jest-message-util@22.4.3", "", { "dependencies": { "@babel/code-frame": "^7.0.0-beta.35", "chalk": "^2.0.1", "micromatch": "^2.3.11", "slash": "^1.0.0", "stack-utils": "^1.0.1" } }, "sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA=="], + + "jest-mock": ["jest-mock@22.4.3", "", {}, "sha512-+4R6mH5M1G4NK16CKg9N1DtCaFmuxhcIqF4lQK/Q1CIotqMs/XBemfpDPeVZBFow6iyUNu6EBT9ugdNOTT5o5Q=="], + + "jest-regex-util": ["jest-regex-util@22.4.3", "", {}, "sha512-LFg1gWr3QinIjb8j833bq7jtQopiwdAs67OGfkPrvy7uNUbVMfTXXcOKXJaeY5GgjobELkKvKENqq1xrUectWg=="], + + "jest-resolve": ["jest-resolve@22.4.3", "", { "dependencies": { "browser-resolve": "^1.11.2", "chalk": "^2.0.1" } }, "sha512-u3BkD/MQBmwrOJDzDIaxpyqTxYH+XqAXzVJP51gt29H8jpj3QgKof5GGO2uPGKGeA1yTMlpbMs1gIQ6U4vcRhw=="], + + "jest-resolve-dependencies": ["jest-resolve-dependencies@22.4.3", "", { "dependencies": { "jest-regex-util": "^22.4.3" } }, "sha512-06czCMVToSN8F2U4EvgSB1Bv/56gc7MpCftZ9z9fBgUQM7dzHGCMBsyfVA6dZTx8v0FDcnALf7hupeQxaBCvpA=="], + + "jest-runner": ["jest-runner@22.4.4", "", { "dependencies": { "exit": "^0.1.2", "jest-config": "^22.4.4", "jest-docblock": "^22.4.0", "jest-haste-map": "^22.4.2", "jest-jasmine2": "^22.4.4", "jest-leak-detector": "^22.4.0", "jest-message-util": "^22.4.0", "jest-runtime": "^22.4.4", "jest-util": "^22.4.1", "jest-worker": "^22.2.2", "throat": "^4.0.0" } }, "sha512-5S/OpB51igQW9xnkM5Tgd/7ZjiAuIoiJAVtvVTBcEBiXBIFzWM3BAMPBM19FX68gRV0KWyFuGKj0EY3M3aceeQ=="], + + "jest-runtime": ["jest-runtime@22.4.4", "", { "dependencies": { "babel-core": "^6.0.0", "babel-jest": "^22.4.4", "babel-plugin-istanbul": "^4.1.5", "chalk": "^2.0.1", "convert-source-map": "^1.4.0", "exit": "^0.1.2", "graceful-fs": "^4.1.11", "jest-config": "^22.4.4", "jest-haste-map": "^22.4.2", "jest-regex-util": "^22.1.0", "jest-resolve": "^22.4.2", "jest-util": "^22.4.1", "jest-validate": "^22.4.4", "json-stable-stringify": "^1.0.1", "micromatch": "^2.3.11", "realpath-native": "^1.0.0", "slash": "^1.0.0", "strip-bom": "3.0.0", "write-file-atomic": "^2.1.0", "yargs": "^10.0.3" } }, "sha512-WRTj9m///npte1YjuphCYX7GRY/c2YvJImU9t7qOwFcqHr4YMzmX6evP/3Sehz5DKW2Vi8ONYPCFWe36JVXxfw=="], + + "jest-serializer": ["jest-serializer@22.4.3", "", {}, "sha512-uPaUAppx4VUfJ0QDerpNdF43F68eqKWCzzhUlKNDsUPhjOon7ZehR4C809GCqh765FoMRtTVUVnGvIoskkYHiw=="], + + "jest-snapshot": ["jest-snapshot@22.4.3", "", { "dependencies": { "chalk": "^2.0.1", "jest-diff": "^22.4.3", "jest-matcher-utils": "^22.4.3", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "pretty-format": "^22.4.3" } }, "sha512-JXA0gVs5YL0HtLDCGa9YxcmmV2LZbwJ+0MfyXBBc5qpgkEYITQFJP7XNhcHFbUvRiniRpRbGVfJrOoYhhGE0RQ=="], + + "jest-util": ["jest-util@22.4.3", "", { "dependencies": { "callsites": "^2.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.11", "is-ci": "^1.0.10", "jest-message-util": "^22.4.3", "mkdirp": "^0.5.1", "source-map": "^0.6.0" } }, "sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ=="], + + "jest-validate": ["jest-validate@22.4.4", "", { "dependencies": { "chalk": "^2.0.1", "jest-config": "^22.4.4", "jest-get-type": "^22.1.0", "leven": "^2.1.0", "pretty-format": "^22.4.0" } }, "sha512-dmlf4CIZRGvkaVg3fa0uetepcua44DHtktHm6rcoNVtYlpwe6fEJRkMFsaUVcFHLzbuBJ2cPw9Gl9TKfnzMVwg=="], + + "jest-worker": ["jest-worker@22.4.3", "", { "dependencies": { "merge-stream": "^1.0.1" } }, "sha512-B1ucW4fI8qVAuZmicFxI1R3kr2fNeYJyvIQ1rKcuLYnenFV5K5aMbxFj6J0i00Ju83S8jP2d7Dz14+AvbIHRYQ=="], + + "js-tokens": ["js-tokens@3.0.2", "", {}, "sha1-mGbfOVECEw449/mWvOtlRDIJwls="], + + "js-yaml": ["js-yaml@3.13.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw=="], + + "jsbn": ["jsbn@0.1.1", "", {}, "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="], + + "jsdom": ["jsdom@11.12.0", "", { "dependencies": { "abab": "^2.0.0", "acorn": "^5.5.3", "acorn-globals": "^4.1.0", "array-equal": "^1.0.0", "cssom": ">= 0.3.2 < 0.4.0", "cssstyle": "^1.0.0", "data-urls": "^1.0.0", "domexception": "^1.0.1", "escodegen": "^1.9.1", "html-encoding-sniffer": "^1.0.2", "left-pad": "^1.3.0", "nwsapi": "^2.0.7", "parse5": "4.0.0", "pn": "^1.1.0", "request": "^2.87.0", "request-promise-native": "^1.0.5", "sax": "^1.2.4", "symbol-tree": "^3.2.2", "tough-cookie": "^2.3.4", "w3c-hr-time": "^1.0.1", "webidl-conversions": "^4.0.2", "whatwg-encoding": "^1.0.3", "whatwg-mimetype": "^2.1.0", "whatwg-url": "^6.4.1", "ws": "^5.2.0", "xml-name-validator": "^3.0.0" } }, "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw=="], + + "jsesc": ["jsesc@1.3.0", "", {}, "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="], + + "jsinspect": ["jsinspect@0.12.7", "", { "dependencies": { "babylon": "6.16.1", "chalk": "^2.1.0", "commander": "^2.11.0", "filepaths": "0.3.0", "stable": "^0.1.6", "strip-indent": "^1.0.1", "strip-json-comments": "1.0.2" } }, "sha512-9pLr5r5moX3XhACEg/nhIlprBuqRDT+loYigZo7hidmfOj0EV2l6ZMk6gmaNMiX6o1YCMod1lWSH3JoX80QHLA=="], + + "json-loader": ["json-loader@0.5.7", "", {}, "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w=="], + + "json-schema": ["json-schema@0.2.3", "", {}, "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="], + + "json-schema-traverse": ["json-schema-traverse@0.3.1", "", {}, "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="], + + "json-stable-stringify": ["json-stable-stringify@1.0.1", "", { "dependencies": { "jsonify": "~0.0.0" } }, "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8="], + + "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="], + + "json5": ["json5@0.5.1", "", {}, "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="], + + "jsonfile": ["jsonfile@2.4.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha1-NzaitCi4e72gzIO1P6PWM6NcKug="], + + "jsonify": ["jsonify@0.0.0", "", {}, "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="], + + "jsprim": ["jsprim@1.4.1", "", { "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" } }, "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI="], + + "jsx-ast-utils": ["jsx-ast-utils@2.0.1", "", { "dependencies": { "array-includes": "^3.0.3" } }, "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8="], + + "just-debounce": ["just-debounce@1.0.0", "", {}, "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo="], + + "kew": ["kew@0.7.0", "", {}, "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s="], + + "kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "klaw": ["klaw@1.3.1", "", { "optionalDependencies": { "graceful-fs": "^4.1.9" } }, "sha1-QIhDO0azsbolnXh4XY6W9zugJDk="], + + "last-run": ["last-run@1.1.1", "", { "dependencies": { "default-resolution": "^2.0.0", "es6-weak-map": "^2.0.1" } }, "sha1-RblpQsF7HHnHchmCWbqUO+v4yls="], + + "lazy-cache": ["lazy-cache@1.0.4", "", {}, "sha1-odePw6UEdMuAhF07O24dpJpEbo4="], + + "lazystream": ["lazystream@1.0.0", "", { "dependencies": { "readable-stream": "^2.0.5" } }, "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ="], + + "lcid": ["lcid@1.0.0", "", { "dependencies": { "invert-kv": "^1.0.0" } }, "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU="], + + "lead": ["lead@1.0.0", "", { "dependencies": { "flush-write-stream": "^1.0.2" } }, "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI="], + + "left-pad": ["left-pad@1.3.0", "", {}, "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA=="], + + "leven": ["leven@2.1.0", "", {}, "sha1-wuep93IJTe6dNCAq6KzORoeHVYA="], + + "levn": ["levn@0.3.0", "", { "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" } }, "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4="], + + "liftoff": ["liftoff@2.5.0", "", { "dependencies": { "extend": "^3.0.0", "findup-sync": "^2.0.0", "fined": "^1.0.1", "flagged-respawn": "^1.0.0", "is-plain-object": "^2.0.4", "object.map": "^1.0.0", "rechoir": "^0.6.2", "resolve": "^1.1.7" } }, "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew="], + + "load-json-file": ["load-json-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "strip-bom": "^2.0.0" } }, "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA="], + + "loader-runner": ["loader-runner@2.3.0", "", {}, "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI="], + + "loader-utils": ["loader-utils@0.2.17", "", { "dependencies": { "big.js": "^3.1.3", "emojis-list": "^2.0.0", "json5": "^0.5.0", "object-assign": "^4.0.1" } }, "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g="], + + "locate-path": ["locate-path@2.0.0", "", { "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4="], + + "lodash": ["lodash@4.17.10", "", {}, "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="], + + "lodash._baseclone": ["lodash._baseclone@4.5.7", "", {}, "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ="], + + "lodash.clone": ["lodash.clone@4.3.2", "", { "dependencies": { "lodash._baseclone": "~4.5.0" } }, "sha1-5WsXa2gjp93jj38r9Y3n1ZcSAOk="], + + "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha1-gteb/zCmfEAF/9XiUVMArZyk168="], + + "lodash.map": ["lodash.map@4.6.0", "", {}, "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM="], + + "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="], + + "lodash.toarray": ["lodash.toarray@4.4.0", "", {}, "sha1-JMS/zWsvuji/0FlNsRedjptlZWE="], + + "longest": ["longest@1.0.1", "", {}, "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="], + + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + + "loud-rejection": ["loud-rejection@1.6.0", "", { "dependencies": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" } }, "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8="], + + "lru-cache": ["lru-cache@4.1.3", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA=="], + + "lru-queue": ["lru-queue@0.1.0", "", { "dependencies": { "es5-ext": "~0.10.2" } }, "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM="], + + "make-iterator": ["make-iterator@1.0.1", "", { "dependencies": { "kind-of": "^6.0.2" } }, "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw=="], + + "makeerror": ["makeerror@1.0.11", "", { "dependencies": { "tmpl": "1.0.x" } }, "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw="], + + "map-cache": ["map-cache@0.2.2", "", {}, "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="], + + "map-visit": ["map-visit@1.0.0", "", { "dependencies": { "object-visit": "^1.0.0" } }, "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48="], + + "matchdep": ["matchdep@2.0.0", "", { "dependencies": { "findup-sync": "^2.0.0", "micromatch": "^3.0.4", "resolve": "^1.4.0", "stack-trace": "0.0.10" } }, "sha1-xvNINKDY28OzfCfui7yyfHd1WC4="], + + "math-random": ["math-random@1.0.1", "", {}, "sha1-izqsWIuKZuSXXjzepn97sylgH6w="], + + "md5.js": ["md5.js@1.3.4", "", { "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" } }, "sha1-6b296UogpawYsENA/Fdk1bCdkB0="], + + "mem": ["mem@1.1.0", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y="], + + "memoizee": ["memoizee@0.4.12", "", { "dependencies": { "d": "1", "es5-ext": "^0.10.30", "es6-weak-map": "^2.0.2", "event-emitter": "^0.3.5", "is-promise": "^2.1", "lru-queue": "0.1", "next-tick": "1", "timers-ext": "^0.1.2" } }, "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg=="], + + "memory-fs": ["memory-fs@0.4.1", "", { "dependencies": { "errno": "^0.1.3", "readable-stream": "^2.0.1" } }, "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI="], + + "merge": ["merge@1.2.0", "", {}, "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo="], + + "merge-stream": ["merge-stream@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.1" } }, "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE="], + + "micromatch": ["micromatch@2.3.11", "", { "dependencies": { "arr-diff": "^2.0.0", "array-unique": "^0.2.1", "braces": "^1.8.2", "expand-brackets": "^0.1.4", "extglob": "^0.3.1", "filename-regex": "^2.0.0", "is-extglob": "^1.0.0", "is-glob": "^2.0.1", "kind-of": "^3.0.2", "normalize-path": "^2.0.1", "object.omit": "^2.0.0", "parse-glob": "^3.0.4", "regex-cache": "^0.4.2" } }, "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU="], + + "miller-rabin": ["miller-rabin@4.0.1", "", { "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" } }, "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA=="], + + "mime-db": ["mime-db@1.35.0", "", {}, "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg=="], + + "mime-types": ["mime-types@2.1.19", "", { "dependencies": { "mime-db": "~1.35.0" } }, "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw=="], + + "mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="], + + "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="], + + "minimalistic-crypto-utils": ["minimalistic-crypto-utils@1.0.1", "", {}, "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="], + + "minimatch": ["minimatch@3.0.4", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA=="], + + "minimist": ["minimist@1.2.0", "", {}, "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="], + + "minipass": ["minipass@2.3.3", "", { "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw=="], + + "minizlib": ["minizlib@1.1.0", "", { "dependencies": { "minipass": "^2.2.1" } }, "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA=="], + + "mixin-deep": ["mixin-deep@1.3.1", "", { "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" } }, "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ=="], + + "mkdirp": ["mkdirp@0.5.1", "", { "dependencies": { "minimist": "0.0.8" } }, "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM="], + + "mkdirp-promise": ["mkdirp-promise@5.0.1", "", { "dependencies": { "mkdirp": "*" } }, "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE="], + + "mock-stdin": ["mock-stdin@0.3.1", "", {}, "sha1-xlfZZC2QeGQ1xkyl6Zu9TQm9fdM="], + + "ms": ["ms@2.0.0", "", {}, "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="], + + "mute-stdout": ["mute-stdout@1.0.0", "", {}, "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0="], + + "mute-stream": ["mute-stream@0.0.7", "", {}, "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="], + + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + + "nan": ["nan@2.10.0", "", {}, "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="], + + "nanomatch": ["nanomatch@1.2.13", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "fragment-cache": "^0.2.1", "is-windows": "^1.0.2", "kind-of": "^6.0.2", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="], + + "needle": ["needle@2.2.1", "", { "dependencies": { "debug": "^2.1.2", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q=="], + + "neo-async": ["neo-async@2.5.1", "", {}, "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA=="], + + "next-tick": ["next-tick@1.0.0", "", {}, "sha1-yobR/ogoFpsBICCOPchCS524NCw="], + + "nice-try": ["nice-try@1.0.4", "", {}, "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA=="], + + "node-emoji": ["node-emoji@1.8.1", "", { "dependencies": { "lodash.toarray": "^4.4.0" } }, "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg=="], + + "node-fetch": ["node-fetch@1.6.3", "", { "dependencies": { "encoding": "^0.1.11", "is-stream": "^1.0.1" } }, "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ="], + + "node-int64": ["node-int64@0.4.0", "", {}, "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs="], + + "node-libs-browser": ["node-libs-browser@2.1.0", "", { "dependencies": { "assert": "^1.1.1", "browserify-zlib": "^0.2.0", "buffer": "^4.3.0", "console-browserify": "^1.1.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", "events": "^1.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "0.0.0", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", "readable-stream": "^2.3.3", "stream-browserify": "^2.0.1", "stream-http": "^2.7.2", "string_decoder": "^1.0.0", "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.10.3", "vm-browserify": "0.0.4" } }, "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg=="], + + "node-notifier": ["node-notifier@5.2.1", "", { "dependencies": { "growly": "^1.3.0", "semver": "^5.4.1", "shellwords": "^0.1.1", "which": "^1.3.0" } }, "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg=="], + + "node-pre-gyp": ["node-pre-gyp@0.10.3", "", { "dependencies": { "detect-libc": "^1.0.2", "mkdirp": "^0.5.1", "needle": "^2.2.1", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4" } }, "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A=="], + + "nopt": ["nopt@4.0.1", "", { "dependencies": { "abbrev": "1", "osenv": "^0.1.4" } }, "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00="], + + "normalize-package-data": ["normalize-package-data@2.4.0", "", { "dependencies": { "hosted-git-info": "^2.1.4", "is-builtin-module": "^1.0.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw=="], + + "normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk="], + + "normalize-url": ["normalize-url@2.0.1", "", { "dependencies": { "prepend-http": "^2.0.0", "query-string": "^5.0.1", "sort-keys": "^2.0.0" } }, "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw=="], + + "now-and-later": ["now-and-later@2.0.0", "", { "dependencies": { "once": "^1.3.2" } }, "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4="], + + "npm-bundled": ["npm-bundled@1.0.3", "", {}, "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow=="], + + "npm-logical-tree": ["npm-logical-tree@1.2.1", "", {}, "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg=="], + + "npm-packlist": ["npm-packlist@1.1.11", "", { "dependencies": { "ignore-walk": "^3.0.1", "npm-bundled": "^1.0.1" } }, "sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA=="], + + "npm-run-path": ["npm-run-path@2.0.2", "", { "dependencies": { "path-key": "^2.0.0" } }, "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8="], + + "npmlog": ["npmlog@4.1.2", "", { "dependencies": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", "gauge": "~2.7.3", "set-blocking": "~2.0.0" } }, "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg=="], + + "number-is-nan": ["number-is-nan@1.0.1", "", {}, "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="], + + "nwsapi": ["nwsapi@2.0.8", "", {}, "sha512-7RZ+qbFGiVc6v14Y8DSZjPN1wZPOaMbiiP4tzf5eNuyOITAeOIA3cMhjuKUypVIqBgCSg1KaSyAv8Ocq/0ZJ1A=="], + + "oauth-sign": ["oauth-sign@0.8.2", "", {}, "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="], + + "object-copy": ["object-copy@0.1.0", "", { "dependencies": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" } }, "sha1-fn2Fi3gb18mRpBupde04EnVOmYw="], + + "object-keys": ["object-keys@1.0.12", "", {}, "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag=="], + + "object-path": ["object-path@0.11.4", "", {}, "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk="], + + "object-visit": ["object-visit@1.0.1", "", { "dependencies": { "isobject": "^3.0.0" } }, "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs="], + + "object.assign": ["object.assign@4.1.0", "", { "dependencies": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", "has-symbols": "^1.0.0", "object-keys": "^1.0.11" } }, "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w=="], + + "object.defaults": ["object.defaults@1.1.0", "", { "dependencies": { "array-each": "^1.0.1", "array-slice": "^1.0.0", "for-own": "^1.0.0", "isobject": "^3.0.0" } }, "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8="], + + "object.getownpropertydescriptors": ["object.getownpropertydescriptors@2.0.3", "", { "dependencies": { "define-properties": "^1.1.2", "es-abstract": "^1.5.1" } }, "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY="], + + "object.map": ["object.map@1.0.1", "", { "dependencies": { "for-own": "^1.0.0", "make-iterator": "^1.0.0" } }, "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc="], + + "object.omit": ["object.omit@2.0.1", "", { "dependencies": { "for-own": "^0.1.4", "is-extendable": "^0.1.1" } }, "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo="], + + "object.pick": ["object.pick@1.3.0", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c="], + + "object.reduce": ["object.reduce@1.0.1", "", { "dependencies": { "for-own": "^1.0.0", "make-iterator": "^1.0.0" } }, "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="], + + "onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ="], + + "opencollective": ["opencollective@1.0.3", "", { "dependencies": { "babel-polyfill": "6.23.0", "chalk": "1.1.3", "inquirer": "3.0.6", "minimist": "1.2.0", "node-fetch": "1.6.3", "opn": "4.0.2" } }, "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE="], + + "opn": ["opn@4.0.2", "", { "dependencies": { "object-assign": "^4.0.1", "pinkie-promise": "^2.0.0" } }, "sha1-erwi5kTf9jsKltWrfyeQwPAavJU="], + + "optimist": ["optimist@0.6.1", "", { "dependencies": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" } }, "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="], + + "optionator": ["optionator@0.8.2", "", { "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "wordwrap": "~1.0.0" } }, "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q="], + + "ordered-read-streams": ["ordered-read-streams@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.1" } }, "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4="], + + "os-browserify": ["os-browserify@0.3.0", "", {}, "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="], + + "os-homedir": ["os-homedir@1.0.2", "", {}, "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="], + + "os-locale": ["os-locale@1.4.0", "", { "dependencies": { "lcid": "^1.0.0" } }, "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk="], + + "os-shim": ["os-shim@0.1.3", "", {}, "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc="], + + "os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="], + + "osenv": ["osenv@0.1.5", "", { "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } }, "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g=="], + + "p-finally": ["p-finally@1.0.0", "", {}, "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="], + + "p-limit": ["p-limit@1.3.0", "", { "dependencies": { "p-try": "^1.0.0" } }, "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q=="], + + "p-locate": ["p-locate@2.0.0", "", { "dependencies": { "p-limit": "^1.1.0" } }, "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM="], + + "p-try": ["p-try@1.0.0", "", {}, "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="], + + "pad-right": ["pad-right@0.2.2", "", { "dependencies": { "repeat-string": "^1.5.2" } }, "sha1-b7ySQEXSRPKiokRQMGDTv8YAl3Q="], + + "pako": ["pako@0.2.9", "", {}, "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="], + + "parse-asn1": ["parse-asn1@5.1.1", "", { "dependencies": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3" } }, "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw=="], + + "parse-filepath": ["parse-filepath@1.0.2", "", { "dependencies": { "is-absolute": "^1.0.0", "map-cache": "^0.2.0", "path-root": "^0.1.1" } }, "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE="], + + "parse-glob": ["parse-glob@3.0.4", "", { "dependencies": { "glob-base": "^0.3.0", "is-dotfile": "^1.0.0", "is-extglob": "^1.0.0", "is-glob": "^2.0.0" } }, "sha1-ssN2z7EfNVE7rdFz7wu246OIORw="], + + "parse-json": ["parse-json@2.2.0", "", { "dependencies": { "error-ex": "^1.2.0" } }, "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck="], + + "parse-passwd": ["parse-passwd@1.0.0", "", {}, "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY="], + + "parse5": ["parse5@4.0.0", "", {}, "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="], + + "pascalcase": ["pascalcase@0.1.1", "", {}, "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="], + + "path-browserify": ["path-browserify@0.0.0", "", {}, "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="], + + "path-dirname": ["path-dirname@1.0.2", "", {}, "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="], + + "path-exists": ["path-exists@2.1.0", "", { "dependencies": { "pinkie-promise": "^2.0.0" } }, "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s="], + + "path-extra": ["path-extra@1.0.3", "", {}, "sha1-fBEhiablDVlXkOetIDfkTkEMEWY="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="], + + "path-is-inside": ["path-is-inside@1.0.2", "", {}, "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="], + + "path-key": ["path-key@2.0.1", "", {}, "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="], + + "path-parse": ["path-parse@1.0.5", "", {}, "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME="], + + "path-root": ["path-root@0.1.1", "", { "dependencies": { "path-root-regex": "^0.1.0" } }, "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc="], + + "path-root-regex": ["path-root-regex@0.1.2", "", {}, "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0="], + + "path-type": ["path-type@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" } }, "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE="], + + "pbkdf2": ["pbkdf2@3.0.16", "", { "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", "ripemd160": "^2.0.1", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" } }, "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA=="], + + "peek-stream": ["peek-stream@1.1.3", "", { "dependencies": { "buffer-from": "^1.0.0", "duplexify": "^3.5.0", "through2": "^2.0.3" } }, "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA=="], + + "performance-now": ["performance-now@2.1.0", "", {}, "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="], + + "pify": ["pify@2.3.0", "", {}, "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="], + + "pinkie": ["pinkie@2.0.4", "", {}, "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="], + + "pinkie-promise": ["pinkie-promise@2.0.1", "", { "dependencies": { "pinkie": "^2.0.0" } }, "sha1-ITXW36ejWMBprJsXh3YogihFD/o="], + + "pkg-dir": ["pkg-dir@1.0.0", "", { "dependencies": { "find-up": "^1.0.0" } }, "sha1-ektQio1bstYp1EcFb/TpyTFM89Q="], + + "plugin-error": ["plugin-error@1.0.1", "", { "dependencies": { "ansi-colors": "^1.0.1", "arr-diff": "^4.0.0", "arr-union": "^3.1.0", "extend-shallow": "^3.0.2" } }, "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA=="], + + "pluralize": ["pluralize@4.0.0", "", {}, "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I="], + + "pn": ["pn@1.1.0", "", {}, "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA=="], + + "posix-character-classes": ["posix-character-classes@0.1.1", "", {}, "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="], + + "prelude-ls": ["prelude-ls@1.1.2", "", {}, "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="], + + "prepend-http": ["prepend-http@2.0.0", "", {}, "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="], + + "preserve": ["preserve@0.2.0", "", {}, "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="], + + "prettier": ["prettier@1.5.2", "", {}, "sha512-f55mvineQ5yc36cLX4n4RWP6JH6MLcfi5f9MVsjpfBs4MVSG2GYT4v6cukzmvkIOvmNOdCZfDSMY3hQcMcDQbQ=="], + + "pretty-format": ["pretty-format@22.4.3", "", { "dependencies": { "ansi-regex": "^3.0.0", "ansi-styles": "^3.2.0" } }, "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ=="], + + "pretty-hrtime": ["pretty-hrtime@1.0.3", "", {}, "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE="], + + "private": ["private@0.1.8", "", {}, "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="], + + "process": ["process@0.11.10", "", {}, "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="], + + "process-nextick-args": ["process-nextick-args@2.0.0", "", {}, "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="], + + "progress": ["progress@2.0.0", "", {}, "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8="], + + "prop-types": ["prop-types@15.6.2", "", { "dependencies": { "loose-envify": "^1.3.1", "object-assign": "^4.1.1" } }, "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ=="], + + "proper-lockfile": ["proper-lockfile@2.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "retry": "^0.10.0" } }, "sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0="], + + "prr": ["prr@1.0.1", "", {}, "sha1-0/wRS6BplaRexok/SEzrHXj19HY="], + + "pseudomap": ["pseudomap@1.0.2", "", {}, "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="], + + "psl": ["psl@1.1.28", "", {}, "sha512-+AqO1Ae+N/4r7Rvchrdm432afjT9hqJRyBN3DQv9At0tPz4hIFSGKbq64fN9dVoCow4oggIIax5/iONx0r9hZw=="], + + "public-encrypt": ["public-encrypt@4.0.2", "", { "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1" } }, "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q=="], + + "puka": ["puka@1.0.0", "", {}, "sha512-JOY9vNkLjpwi/CtwsZfGcZZiHb+HfOJjjdz93v6150EPNQgb5JDeImlI48r/kZ5i9bNCSjXpU+eyYIxoujhNLw=="], + + "pump": ["pump@1.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw=="], + + "pumpify": ["pumpify@1.5.1", "", { "dependencies": { "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" } }, "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ=="], + + "punycode": ["punycode@1.4.1", "", {}, "sha1-wNWmOycYgArY4esPpSachN1BhF4="], + + "qs": ["qs@6.5.2", "", {}, "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="], + + "query-string": ["query-string@5.1.1", "", { "dependencies": { "decode-uri-component": "^0.2.0", "object-assign": "^4.1.0", "strict-uri-encode": "^1.0.0" } }, "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw=="], + + "querystring": ["querystring@0.2.0", "", {}, "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="], + + "querystring-es3": ["querystring-es3@0.2.1", "", {}, "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="], + + "randomatic": ["randomatic@3.0.0", "", { "dependencies": { "is-number": "^4.0.0", "kind-of": "^6.0.0", "math-random": "^1.0.1" } }, "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA=="], + + "randombytes": ["randombytes@2.0.6", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A=="], + + "randomfill": ["randomfill@1.0.4", "", { "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw=="], + + "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], + + "read": ["read@1.0.7", "", { "dependencies": { "mute-stream": "~0.0.4" } }, "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ="], + + "read-pkg": ["read-pkg@1.1.0", "", { "dependencies": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", "path-type": "^1.0.0" } }, "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg="], + + "read-pkg-up": ["read-pkg-up@1.0.1", "", { "dependencies": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" } }, "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI="], + + "readable-stream": ["readable-stream@2.3.6", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw=="], + + "readdirp": ["readdirp@2.1.0", "", { "dependencies": { "graceful-fs": "^4.1.2", "minimatch": "^3.0.2", "readable-stream": "^2.0.2", "set-immediate-shim": "^1.0.1" } }, "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg="], + + "realpath-native": ["realpath-native@1.0.1", "", { "dependencies": { "util.promisify": "^1.0.0" } }, "sha512-W14EcXuqUvKP8dkWkD7B95iMy77lpMnlFXbbk409bQtNCbeu0kvRE5reo+yIZ3JXxg6frbGsz2DLQ39lrCB40g=="], + + "rechoir": ["rechoir@0.6.2", "", { "dependencies": { "resolve": "^1.1.6" } }, "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q="], + + "regenerate": ["regenerate@1.4.0", "", {}, "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="], + + "regenerator-runtime": ["regenerator-runtime@0.11.1", "", {}, "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="], + + "regenerator-transform": ["regenerator-transform@0.10.1", "", { "dependencies": { "babel-runtime": "^6.18.0", "babel-types": "^6.19.0", "private": "^0.1.6" } }, "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q=="], + + "regex-cache": ["regex-cache@0.4.4", "", { "dependencies": { "is-equal-shallow": "^0.1.3" } }, "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ=="], + + "regex-not": ["regex-not@1.0.2", "", { "dependencies": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" } }, "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A=="], + + "regexpu-core": ["regexpu-core@2.0.0", "", { "dependencies": { "regenerate": "^1.2.1", "regjsgen": "^0.2.0", "regjsparser": "^0.1.4" } }, "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA="], + + "regjsgen": ["regjsgen@0.2.0", "", {}, "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="], + + "regjsparser": ["regjsparser@0.1.5", "", { "dependencies": { "jsesc": "~0.5.0" } }, "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw="], + + "remove-bom-buffer": ["remove-bom-buffer@3.0.0", "", { "dependencies": { "is-buffer": "^1.1.5", "is-utf8": "^0.2.1" } }, "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ=="], + + "remove-bom-stream": ["remove-bom-stream@1.2.0", "", { "dependencies": { "remove-bom-buffer": "^3.0.0", "safe-buffer": "^5.1.0", "through2": "^2.0.3" } }, "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM="], + + "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="], + + "repeat-element": ["repeat-element@1.1.2", "", {}, "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo="], + + "repeat-string": ["repeat-string@1.6.1", "", {}, "sha1-jcrkcOHIirwtYA//Sndihtp15jc="], + + "repeating": ["repeating@2.0.1", "", { "dependencies": { "is-finite": "^1.0.0" } }, "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo="], + + "replace-ext": ["replace-ext@0.0.1", "", {}, "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ="], + + "replace-homedir": ["replace-homedir@1.0.0", "", { "dependencies": { "homedir-polyfill": "^1.0.1", "is-absolute": "^1.0.0", "remove-trailing-separator": "^1.1.0" } }, "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw="], + + "request": ["request@2.87.0", "", { "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.6.0", "caseless": "~0.12.0", "combined-stream": "~1.0.5", "extend": "~3.0.1", "forever-agent": "~0.6.1", "form-data": "~2.3.1", "har-validator": "~5.0.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.17", "oauth-sign": "~0.8.2", "performance-now": "^2.1.0", "qs": "~6.5.1", "safe-buffer": "^5.1.1", "tough-cookie": "~2.3.3", "tunnel-agent": "^0.6.0", "uuid": "^3.1.0" } }, "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw=="], + + "request-capture-har": ["request-capture-har@1.2.2", "", {}, "sha1-zWks+yzHRP2EozWKrG7lFSjPcg0="], + + "request-promise-core": ["request-promise-core@1.1.1", "", { "dependencies": { "lodash": "^4.13.1" } }, "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY="], + + "request-promise-native": ["request-promise-native@1.0.5", "", { "dependencies": { "request-promise-core": "1.1.1", "stealthy-require": "^1.1.0", "tough-cookie": ">=2.3.3" } }, "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="], + + "require-main-filename": ["require-main-filename@1.0.1", "", {}, "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="], + + "require-resolve": ["require-resolve@0.0.2", "", { "dependencies": { "x-path": "^0.0.2" } }, "sha1-urQQqxruLz9Vt5MXRR3TQodk5vM="], + + "require-uncached": ["require-uncached@1.0.3", "", { "dependencies": { "caller-path": "^0.1.0", "resolve-from": "^1.0.0" } }, "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM="], + + "resolve": ["resolve@1.8.1", "", { "dependencies": { "path-parse": "^1.0.5" } }, "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA=="], + + "resolve-cwd": ["resolve-cwd@2.0.0", "", { "dependencies": { "resolve-from": "^3.0.0" } }, "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo="], + + "resolve-dir": ["resolve-dir@0.1.1", "", { "dependencies": { "expand-tilde": "^1.2.2", "global-modules": "^0.2.3" } }, "sha1-shklmlYC+sXFxJatiUpujMQwJh4="], + + "resolve-from": ["resolve-from@1.0.1", "", {}, "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY="], + + "resolve-options": ["resolve-options@1.1.0", "", { "dependencies": { "value-or-function": "^3.0.0" } }, "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE="], + + "resolve-url": ["resolve-url@0.2.1", "", {}, "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="], + + "restore-cursor": ["restore-cursor@2.0.0", "", { "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" } }, "sha1-n37ih/gv0ybU/RYpI9YhKe7g368="], + + "ret": ["ret@0.1.15", "", {}, "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="], + + "retry": ["retry@0.10.1", "", {}, "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q="], + + "right-align": ["right-align@0.1.3", "", { "dependencies": { "align-text": "^0.1.1" } }, "sha1-YTObci/mo1FWiSENJOFMlhSGE+8="], + + "right-pad": ["right-pad@1.0.1", "", {}, "sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA="], + + "rimraf": ["rimraf@2.6.2", "", { "dependencies": { "glob": "^7.0.5" } }, "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w=="], + + "ripemd160": ["ripemd160@2.0.2", "", { "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" } }, "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA=="], + + "rsvp": ["rsvp@3.2.1", "", {}, "sha1-B8tKXfJa3Z6Cbrxn3Mn9idsn2Eo="], + + "run-async": ["run-async@2.3.0", "", { "dependencies": { "is-promise": "^2.1.0" } }, "sha1-A3GrSuC91yDUFm19/aZP96RFpsA="], + + "rx": ["rx@4.1.0", "", {}, "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I="], + + "rx-lite": ["rx-lite@4.0.8", "", {}, "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ="], + + "rx-lite-aggregates": ["rx-lite-aggregates@4.0.8", "", { "dependencies": { "rx-lite": "*" } }, "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74="], + + "rxjs": ["rxjs@6.3.3", "", { "dependencies": { "tslib": "^1.9.0" } }, "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "safe-regex": ["safe-regex@1.1.0", "", { "dependencies": { "ret": "~0.1.10" } }, "sha1-QKNmnzsHfR6UPURinhV91IAjvy4="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "sane": ["sane@2.5.2", "", { "dependencies": { "anymatch": "^2.0.0", "capture-exit": "^1.2.0", "exec-sh": "^0.2.0", "fb-watchman": "^2.0.0", "micromatch": "^3.1.4", "minimist": "^1.1.1", "walker": "~1.0.5", "watch": "~0.18.0" }, "optionalDependencies": { "fsevents": "^1.2.3" } }, "sha1-tNwYYcIbQn6SlQej51HiosuKs/o="], + + "sax": ["sax@1.2.4", "", {}, "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="], + + "schema-utils": ["schema-utils@0.4.7", "", { "dependencies": { "ajv": "^6.1.0", "ajv-keywords": "^3.1.0" } }, "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ=="], + + "semver": ["semver@5.5.0", "", {}, "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="], + + "semver-greatest-satisfied-range": ["semver-greatest-satisfied-range@1.1.0", "", { "dependencies": { "sver-compat": "^1.5.0" } }, "sha1-E+jCZYq5aRywzXEJMkAoDTb3els="], + + "set-blocking": ["set-blocking@2.0.0", "", {}, "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="], + + "set-immediate-shim": ["set-immediate-shim@1.0.1", "", {}, "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="], + + "set-value": ["set-value@2.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" } }, "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg=="], + + "setimmediate": ["setimmediate@1.0.5", "", {}, "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="], + + "sha.js": ["sha.js@2.4.11", "", { "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ=="], + + "shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo="], + + "shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="], + + "shelljs": ["shelljs@0.7.6", "", { "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" } }, "sha1-N5zM+1a5HIYB5HkzVutTgpJN6a0="], + + "shellwords": ["shellwords@0.1.1", "", {}, "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww=="], + + "signal-exit": ["signal-exit@3.0.2", "", {}, "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="], + + "slash": ["slash@1.0.0", "", {}, "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="], + + "slice-ansi": ["slice-ansi@1.0.0", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0" } }, "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg=="], + + "snapdragon": ["snapdragon@0.8.2", "", { "dependencies": { "base": "^0.11.1", "debug": "^2.2.0", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "map-cache": "^0.2.2", "source-map": "^0.5.6", "source-map-resolve": "^0.5.0", "use": "^3.1.0" } }, "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg=="], + + "snapdragon-node": ["snapdragon-node@2.1.1", "", { "dependencies": { "define-property": "^1.0.0", "isobject": "^3.0.0", "snapdragon-util": "^3.0.1" } }, "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw=="], + + "snapdragon-util": ["snapdragon-util@3.0.1", "", { "dependencies": { "kind-of": "^3.2.0" } }, "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ=="], + + "sort-keys": ["sort-keys@2.0.0", "", { "dependencies": { "is-plain-obj": "^1.0.0" } }, "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg="], + + "source-list-map": ["source-list-map@2.0.0", "", {}, "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A=="], + + "source-map": ["source-map@0.5.7", "", {}, "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="], + + "source-map-resolve": ["source-map-resolve@0.5.2", "", { "dependencies": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", "urix": "^0.1.0" } }, "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA=="], + + "source-map-support": ["source-map-support@0.4.18", "", { "dependencies": { "source-map": "^0.5.6" } }, "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA=="], + + "source-map-url": ["source-map-url@0.4.0", "", {}, "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="], + + "sparkles": ["sparkles@1.0.1", "", {}, "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw=="], + + "spawn-sync": ["spawn-sync@1.0.15", "", { "dependencies": { "concat-stream": "^1.4.7", "os-shim": "^0.1.2" } }, "sha1-sAeZVX63+wyDdsKdROih6mfldHY="], + + "spdx-correct": ["spdx-correct@3.0.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g=="], + + "spdx-exceptions": ["spdx-exceptions@2.1.0", "", {}, "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg=="], + + "spdx-expression-parse": ["spdx-expression-parse@3.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg=="], + + "spdx-license-ids": ["spdx-license-ids@3.0.0", "", {}, "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA=="], + + "split-string": ["split-string@3.1.0", "", { "dependencies": { "extend-shallow": "^3.0.0" } }, "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="], + + "sshpk": ["sshpk@1.14.2", "", { "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "dashdash": "^1.12.0", "getpass": "^0.1.1", "safer-buffer": "^2.0.2" }, "optionalDependencies": { "bcrypt-pbkdf": "^1.0.0", "ecc-jsbn": "~0.1.1", "jsbn": "~0.1.0", "tweetnacl": "~0.14.0" } }, "sha1-xvxhZIo9nE52T9P8306hBeSSupg="], + + "ssri": ["ssri@5.3.0", "", { "dependencies": { "safe-buffer": "^5.1.1" } }, "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ=="], + + "stable": ["stable@0.1.8", "", {}, "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w=="], + + "stack-trace": ["stack-trace@0.0.10", "", {}, "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="], + + "stack-utils": ["stack-utils@1.0.1", "", {}, "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA="], + + "static-extend": ["static-extend@0.1.2", "", { "dependencies": { "define-property": "^0.2.5", "object-copy": "^0.1.0" } }, "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY="], + + "stealthy-require": ["stealthy-require@1.1.1", "", {}, "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="], + + "stream-browserify": ["stream-browserify@2.0.1", "", { "dependencies": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" } }, "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds="], + + "stream-exhaust": ["stream-exhaust@1.0.2", "", {}, "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw=="], + + "stream-http": ["stream-http@2.8.3", "", { "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" } }, "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw=="], + + "stream-shift": ["stream-shift@1.0.0", "", {}, "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="], + + "strict-uri-encode": ["strict-uri-encode@1.1.0", "", {}, "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="], + + "string-length": ["string-length@2.0.0", "", { "dependencies": { "astral-regex": "^1.0.0", "strip-ansi": "^4.0.0" } }, "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0="], + + "string-replace-loader": ["string-replace-loader@2.1.1", "", { "dependencies": { "loader-utils": "^1.1.0", "schema-utils": "^0.4.5" } }, "sha512-0Nvw1LDclF45AFNuYPcD2Jvkv0mwb/dQSnJZMvhqGrT+zzmrpG3OJFD600qfQfNUd5aqfp7fCm2mQMfF7zLbyQ=="], + + "string-width": ["string-width@1.0.2", "", { "dependencies": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } }, "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M="], + + "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + + "strip-ansi": ["strip-ansi@4.0.0", "", { "dependencies": { "ansi-regex": "^3.0.0" } }, "sha1-qEeQIusaw2iocTibY1JixQXuNo8="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="], + + "strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI="], + + "strip-eof": ["strip-eof@1.0.0", "", {}, "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="], + + "strip-indent": ["strip-indent@1.0.1", "", { "dependencies": { "get-stdin": "^4.0.1" } }, "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI="], + + "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha1-PFMZQukIwml8DsNEhYwobHygpgo="], + + "supports-color": ["supports-color@3.2.3", "", { "dependencies": { "has-flag": "^1.0.0" } }, "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY="], + + "sver-compat": ["sver-compat@1.5.0", "", { "dependencies": { "es6-iterator": "^2.0.1", "es6-symbol": "^3.1.1" } }, "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg="], + + "symbol-tree": ["symbol-tree@3.2.2", "", {}, "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY="], + + "table": ["table@4.0.3", "", { "dependencies": { "ajv": "^6.0.1", "ajv-keywords": "^3.0.0", "chalk": "^2.1.0", "lodash": "^4.17.4", "slice-ansi": "1.0.0", "string-width": "^2.1.1" } }, "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg=="], + + "tapable": ["tapable@0.2.8", "", {}, "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI="], + + "tar": ["tar@4.4.6", "", { "dependencies": { "chownr": "^1.0.1", "fs-minipass": "^1.2.5", "minipass": "^2.3.3", "minizlib": "^1.1.0", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.2" } }, "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg=="], + + "tar-fs": ["tar-fs@1.16.3", "", { "dependencies": { "chownr": "^1.0.1", "mkdirp": "^0.5.1", "pump": "^1.0.0", "tar-stream": "^1.1.2" } }, "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw=="], + + "tar-stream": ["tar-stream@1.6.1", "", { "dependencies": { "bl": "^1.0.0", "buffer-alloc": "^1.1.0", "end-of-stream": "^1.0.0", "fs-constants": "^1.0.0", "readable-stream": "^2.3.0", "to-buffer": "^1.1.0", "xtend": "^4.0.0" } }, "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA=="], + + "temp": ["temp@0.8.3", "", { "dependencies": { "os-tmpdir": "^1.0.0", "rimraf": "~2.2.6" } }, "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k="], + + "ternary-stream": ["ternary-stream@2.0.1", "", { "dependencies": { "duplexify": "^3.5.0", "fork-stream": "^0.0.4", "merge-stream": "^1.0.0", "through2": "^2.0.1" } }, "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk="], + + "test-exclude": ["test-exclude@4.2.1", "", { "dependencies": { "arrify": "^1.0.1", "micromatch": "^3.1.8", "object-assign": "^4.1.0", "read-pkg-up": "^1.0.1", "require-main-filename": "^1.0.1" } }, "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ=="], + + "text-table": ["text-table@0.2.0", "", {}, "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="], + + "thenify": ["thenify@3.3.0", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY="], + + "throat": ["throat@4.1.0", "", {}, "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo="], + + "through": ["through@2.3.8", "", {}, "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="], + + "through2": ["through2@2.0.3", "", { "dependencies": { "readable-stream": "^2.1.5", "xtend": "~4.0.1" } }, "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4="], + + "through2-filter": ["through2-filter@2.0.0", "", { "dependencies": { "through2": "~2.0.0", "xtend": "~4.0.0" } }, "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw="], + + "time-stamp": ["time-stamp@1.1.0", "", {}, "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM="], + + "timers-browserify": ["timers-browserify@2.0.10", "", { "dependencies": { "setimmediate": "^1.0.4" } }, "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg=="], + + "timers-ext": ["timers-ext@0.1.5", "", { "dependencies": { "es5-ext": "~0.10.14", "next-tick": "1" } }, "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg=="], + + "tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], + + "tmpl": ["tmpl@1.0.4", "", {}, "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE="], + + "to-absolute-glob": ["to-absolute-glob@2.0.2", "", { "dependencies": { "is-absolute": "^1.0.0", "is-negated-glob": "^1.0.0" } }, "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs="], + + "to-arraybuffer": ["to-arraybuffer@1.0.1", "", {}, "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="], + + "to-buffer": ["to-buffer@1.1.1", "", {}, "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="], + + "to-fast-properties": ["to-fast-properties@1.0.3", "", {}, "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="], + + "to-object-path": ["to-object-path@0.3.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68="], + + "to-regex": ["to-regex@3.0.2", "", { "dependencies": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" } }, "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw=="], + + "to-regex-range": ["to-regex-range@2.1.1", "", { "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" } }, "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg="], + + "to-through": ["to-through@2.0.0", "", { "dependencies": { "through2": "^2.0.3" } }, "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY="], + + "tough-cookie": ["tough-cookie@2.3.4", "", { "dependencies": { "punycode": "^1.4.1" } }, "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA=="], + + "tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk="], + + "trim-right": ["trim-right@1.0.1", "", {}, "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="], + + "tslib": ["tslib@1.9.3", "", {}, "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="], + + "tty-browserify": ["tty-browserify@0.0.0", "", {}, "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="], + + "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0="], + + "tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="], + + "type-check": ["type-check@0.3.2", "", { "dependencies": { "prelude-ls": "~1.1.2" } }, "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I="], + + "typedarray": ["typedarray@0.0.6", "", {}, "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="], + + "uglify-js": ["uglify-js@2.8.29", "", { "dependencies": { "source-map": "~0.5.1", "yargs": "~3.10.0" }, "optionalDependencies": { "uglify-to-browserify": "~1.0.0" } }, "sha1-KcVzMUgFe7Th913zW3qcty5qWd0="], + + "uglify-to-browserify": ["uglify-to-browserify@1.0.2", "", {}, "sha1-bgkk1r2mta/jSeOabWMoUKD4grc="], + + "unc-path-regex": ["unc-path-regex@0.1.2", "", {}, "sha1-5z3T17DXxe2G+6xrCufYxqadUPo="], + + "undertaker": ["undertaker@1.2.0", "", { "dependencies": { "arr-flatten": "^1.0.1", "arr-map": "^2.0.0", "bach": "^1.0.0", "collection-map": "^1.0.0", "es6-weak-map": "^2.0.1", "last-run": "^1.1.0", "object.defaults": "^1.0.0", "object.reduce": "^1.0.0", "undertaker-registry": "^1.0.0" } }, "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k="], + + "undertaker-registry": ["undertaker-registry@1.0.1", "", {}, "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA="], + + "union-value": ["union-value@1.0.0", "", { "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^0.4.3" } }, "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ="], + + "unique-stream": ["unique-stream@2.2.1", "", { "dependencies": { "json-stable-stringify": "^1.0.0", "through2-filter": "^2.0.0" } }, "sha1-WqADz76Uxf+GbE59ZouxxNuts2k="], + + "unset-value": ["unset-value@1.0.0", "", { "dependencies": { "has-value": "^0.3.1", "isobject": "^3.0.0" } }, "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk="], + + "upath": ["upath@1.1.0", "", {}, "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw=="], + + "uri-js": ["uri-js@4.2.2", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ=="], + + "urix": ["urix@0.1.0", "", {}, "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="], + + "url": ["url@0.11.0", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE="], + + "use": ["use@3.1.1", "", {}, "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="], + + "util": ["util@0.10.4", "", { "dependencies": { "inherits": "2.0.3" } }, "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="], + + "util.promisify": ["util.promisify@1.0.0", "", { "dependencies": { "define-properties": "^1.1.2", "object.getownpropertydescriptors": "^2.0.3" } }, "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA=="], + + "uuid": ["uuid@3.3.2", "", {}, "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="], + + "v8-compile-cache": ["v8-compile-cache@2.0.0", "", {}, "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg=="], + + "v8flags": ["v8flags@3.1.1", "", { "dependencies": { "homedir-polyfill": "^1.0.1" } }, "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ=="], + + "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], + + "value-or-function": ["value-or-function@3.0.0", "", {}, "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM="], + + "verror": ["verror@1.10.0", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA="], + + "vinyl": ["vinyl@2.2.0", "", { "dependencies": { "clone": "^2.1.1", "clone-buffer": "^1.0.0", "clone-stats": "^1.0.0", "cloneable-readable": "^1.0.0", "remove-trailing-separator": "^1.0.1", "replace-ext": "^1.0.0" } }, "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg=="], + + "vinyl-fs": ["vinyl-fs@3.0.3", "", { "dependencies": { "fs-mkdirp-stream": "^1.0.0", "glob-stream": "^6.1.0", "graceful-fs": "^4.0.0", "is-valid-glob": "^1.0.0", "lazystream": "^1.0.0", "lead": "^1.0.0", "object.assign": "^4.0.4", "pumpify": "^1.3.5", "readable-stream": "^2.3.3", "remove-bom-buffer": "^3.0.0", "remove-bom-stream": "^1.2.0", "resolve-options": "^1.1.0", "through2": "^2.0.0", "to-through": "^2.0.0", "value-or-function": "^3.0.0", "vinyl": "^2.0.0", "vinyl-sourcemap": "^1.1.0" } }, "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng=="], + + "vinyl-sourcemap": ["vinyl-sourcemap@1.1.0", "", { "dependencies": { "append-buffer": "^1.0.2", "convert-source-map": "^1.5.0", "graceful-fs": "^4.1.6", "normalize-path": "^2.1.1", "now-and-later": "^2.0.0", "remove-bom-buffer": "^3.0.0", "vinyl": "^2.0.0" } }, "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY="], + + "vinyl-sourcemaps-apply": ["vinyl-sourcemaps-apply@0.2.1", "", { "dependencies": { "source-map": "^0.5.1" } }, "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU="], + + "vm-browserify": ["vm-browserify@0.0.4", "", { "dependencies": { "indexof": "0.0.1" } }, "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM="], + + "w3c-hr-time": ["w3c-hr-time@1.0.1", "", { "dependencies": { "browser-process-hrtime": "^0.1.2" } }, "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU="], + + "walker": ["walker@1.0.7", "", { "dependencies": { "makeerror": "1.0.x" } }, "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs="], + + "watch": ["watch@0.18.0", "", { "dependencies": { "exec-sh": "^0.2.0", "minimist": "^1.2.0" } }, "sha1-KAlUdsbffJDJYxOJkMClQj60uYY="], + + "watchpack": ["watchpack@1.6.0", "", { "dependencies": { "chokidar": "^2.0.2", "graceful-fs": "^4.1.2", "neo-async": "^2.5.0" } }, "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA=="], + + "webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], + + "webpack": ["webpack@2.7.0", "", { "dependencies": { "acorn": "^5.0.0", "acorn-dynamic-import": "^2.0.0", "ajv": "^4.7.0", "ajv-keywords": "^1.1.1", "async": "^2.1.2", "enhanced-resolve": "^3.3.0", "interpret": "^1.0.0", "json-loader": "^0.5.4", "json5": "^0.5.1", "loader-runner": "^2.3.0", "loader-utils": "^0.2.16", "memory-fs": "~0.4.1", "mkdirp": "~0.5.0", "node-libs-browser": "^2.0.0", "source-map": "^0.5.3", "supports-color": "^3.1.0", "tapable": "~0.2.5", "uglify-js": "^2.8.27", "watchpack": "^1.3.1", "webpack-sources": "^1.0.1", "yargs": "^6.0.0" } }, "sha512-MjAA0ZqO1ba7ZQJRnoCdbM56mmFpipOPUv/vQpwwfSI42p5PVDdoiuK2AL2FwFUVgT859Jr43bFZXRg/LNsqvg=="], + + "webpack-sources": ["webpack-sources@1.1.0", "", { "dependencies": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" } }, "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw=="], + + "whatwg-encoding": ["whatwg-encoding@1.0.3", "", { "dependencies": { "iconv-lite": "0.4.19" } }, "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw=="], + + "whatwg-mimetype": ["whatwg-mimetype@2.1.0", "", {}, "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew=="], + + "whatwg-url": ["whatwg-url@6.5.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ=="], + + "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], + + "which-module": ["which-module@1.0.0", "", {}, "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="], + + "wide-align": ["wide-align@1.1.3", "", { "dependencies": { "string-width": "^1.0.2 || 2" } }, "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA=="], + + "window-size": ["window-size@0.1.0", "", {}, "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="], + + "word-wrap": ["word-wrap@1.2.3", "", {}, "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="], + + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="], + + "wrap-ansi": ["wrap-ansi@2.1.0", "", { "dependencies": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" } }, "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="], + + "write": ["write@0.2.1", "", { "dependencies": { "mkdirp": "^0.5.1" } }, "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c="], + + "write-file-atomic": ["write-file-atomic@2.3.0", "", { "dependencies": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", "signal-exit": "^3.0.2" } }, "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA=="], + + "ws": ["ws@5.2.2", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA=="], + + "x-path": ["x-path@0.0.2", "", { "dependencies": { "path-extra": "^1.0.2" } }, "sha1-KU0Ha7l6dwbMBwu7Km/YxU32exI="], + + "xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="], + + "xtend": ["xtend@4.0.1", "", {}, "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="], + + "y18n": ["y18n@3.2.1", "", {}, "sha1-bRX7qITAhnnA136I53WegR4H+kE="], + + "yallist": ["yallist@2.1.2", "", {}, "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="], + + "yargs": ["yargs@6.6.0", "", { "dependencies": { "camelcase": "^3.0.0", "cliui": "^3.2.0", "decamelize": "^1.1.1", "get-caller-file": "^1.0.1", "os-locale": "^1.4.0", "read-pkg-up": "^1.0.1", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^1.0.2", "which-module": "^1.0.0", "y18n": "^3.2.1", "yargs-parser": "^4.2.0" } }, "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg="], + + "yargs-parser": ["yargs-parser@4.2.1", "", { "dependencies": { "camelcase": "^3.0.0" } }, "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw="], + + "yn": ["yn@2.0.0", "", {}, "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo="], + + "@gulp-sourcemaps/identity-map/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "acorn-dynamic-import/acorn": ["acorn@4.0.13", "", {}, "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="], + + "acorn-jsx/acorn": ["acorn@3.3.0", "", {}, "sha1-ReN/s56No/JbruP/U2niu18iAXo="], + + "anymatch/micromatch": ["micromatch@3.1.10", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="], + + "array-sort/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "assert/util": ["util@0.10.3", "", { "dependencies": { "inherits": "2.0.1" } }, "sha1-evsa/lCAUkZInj23/g7TeTNqwPk="], + + "async-done/process-nextick-args": ["process-nextick-args@1.0.7", "", {}, "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="], + + "babel-code-frame/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="], + + "babel-core/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "babel-generator/detect-indent": ["detect-indent@4.0.0", "", { "dependencies": { "repeating": "^2.0.0" } }, "sha1-920GQ1LN9Docts5hnE7jqUdd4gg="], + + "babel-plugin-istanbul/find-up": ["find-up@2.1.0", "", { "dependencies": { "locate-path": "^2.0.0" } }, "sha1-RdG35QbHF93UgndaK3eSCjwMV6c="], + + "babel-polyfill/regenerator-runtime": ["regenerator-runtime@0.10.5", "", {}, "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="], + + "babel-traverse/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "base/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "broccoli-kitchen-sink-helpers/glob": ["glob@5.0.15", "", { "dependencies": { "inflight": "^1.0.4", "inherits": "2", "minimatch": "2 || 3", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E="], + + "browser-resolve/resolve": ["resolve@1.1.7", "", {}, "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs="], + + "capture-exit/rsvp": ["rsvp@3.6.2", "", {}, "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw=="], + + "chalk/supports-color": ["supports-color@5.4.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w=="], + + "chokidar/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], + + "chokidar/is-glob": ["is-glob@4.0.0", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A="], + + "class-utils/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "cliui/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "collection-map/for-own": ["for-own@1.0.0", "", { "dependencies": { "for-in": "^1.0.1" } }, "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs="], + + "commitizen/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="], + + "commitizen/cz-conventional-changelog": ["cz-conventional-changelog@2.0.0", "", { "dependencies": { "conventional-commit-types": "^2.0.0", "lodash.map": "^4.5.1", "longest": "^1.0.1", "pad-right": "^0.2.2", "right-pad": "^1.0.1", "word-wrap": "^1.0.3" } }, "sha1-Val5r9/pXnAkh50qD1kkYwFwtTM="], + + "commitizen/detect-indent": ["detect-indent@4.0.0", "", { "dependencies": { "repeating": "^2.0.0" } }, "sha1-920GQ1LN9Docts5hnE7jqUdd4gg="], + + "commitizen/glob": ["glob@7.1.1", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.2", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha1-gFIR3wT6rxxjo2ADBs31reULLsg="], + + "commitizen/inquirer": ["inquirer@1.2.3", "", { "dependencies": { "ansi-escapes": "^1.1.0", "chalk": "^1.0.0", "cli-cursor": "^1.0.1", "cli-width": "^2.0.0", "external-editor": "^1.1.0", "figures": "^1.3.5", "lodash": "^4.3.0", "mute-stream": "0.0.6", "pinkie-promise": "^2.0.0", "run-async": "^2.2.0", "rx": "^4.1.0", "string-width": "^1.0.1", "strip-ansi": "^3.0.0", "through": "^2.3.6" } }, "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg="], + + "commitizen/lodash": ["lodash@4.17.5", "", {}, "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="], + + "css/source-map": ["source-map@0.1.43", "", { "dependencies": { "amdefine": ">=0.0.4" } }, "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y="], + + "data-urls/abab": ["abab@1.0.4", "", {}, "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4="], + + "default-compare/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "encoding/iconv-lite": ["iconv-lite@0.4.23", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA=="], + + "escodegen/esprima": ["esprima@3.1.3", "", {}, "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="], + + "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "eslint/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="], + + "eslint/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "eslint/inquirer": ["inquirer@3.3.0", "", { "dependencies": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.0", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", "external-editor": "^2.0.4", "figures": "^2.0.0", "lodash": "^4.3.0", "mute-stream": "0.0.7", "run-async": "^2.2.0", "rx-lite": "^4.0.8", "rx-lite-aggregates": "^4.0.8", "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" } }, "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ=="], + + "eslint/js-yaml": ["js-yaml@3.12.0", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A=="], + + "execa/cross-spawn": ["cross-spawn@6.0.5", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ=="], + + "extend-shallow/is-extendable": ["is-extendable@1.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4" } }, "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="], + + "fill-range/is-number": ["is-number@2.1.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8="], + + "fill-range/isobject": ["isobject@2.1.0", "", { "dependencies": { "isarray": "1.0.0" } }, "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk="], + + "fined/expand-tilde": ["expand-tilde@2.0.2", "", { "dependencies": { "homedir-polyfill": "^1.0.1" } }, "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI="], + + "gauge/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "get-stream/pump": ["pump@3.0.0", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww=="], + + "glob-base/glob-parent": ["glob-parent@2.0.0", "", { "dependencies": { "is-glob": "^2.0.0" } }, "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg="], + + "glob-parent/is-glob": ["is-glob@3.1.0", "", { "dependencies": { "is-extglob": "^2.1.0" } }, "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo="], + + "global-modules/is-windows": ["is-windows@0.2.0", "", {}, "sha1-3hqm1j6indJIc3tp8f+LgALSEIw="], + + "global-prefix/is-windows": ["is-windows@0.2.0", "", {}, "sha1-3hqm1j6indJIc3tp8f+LgALSEIw="], + + "gulp-cli/yargs": ["yargs@7.1.0", "", { "dependencies": { "camelcase": "^3.0.0", "cliui": "^3.2.0", "decamelize": "^1.1.1", "get-caller-file": "^1.0.1", "os-locale": "^1.4.0", "read-pkg-up": "^1.0.1", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^1.0.2", "which-module": "^1.0.0", "y18n": "^3.2.1", "yargs-parser": "^5.0.0" } }, "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg="], + + "gulp-newer/plugin-error": ["plugin-error@0.1.2", "", { "dependencies": { "ansi-cyan": "^0.1.1", "ansi-red": "^0.1.1", "arr-diff": "^1.0.1", "arr-union": "^2.0.1", "extend-shallow": "^1.1.2" } }, "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4="], + + "gulp-plumber/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="], + + "gulp-plumber/plugin-error": ["plugin-error@0.1.2", "", { "dependencies": { "ansi-cyan": "^0.1.1", "ansi-red": "^0.1.1", "arr-diff": "^1.0.1", "arr-union": "^2.0.1", "extend-shallow": "^1.1.2" } }, "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4="], + + "gulp-sourcemaps/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "handlebars/async": ["async@1.5.2", "", {}, "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="], + + "handlebars/source-map": ["source-map@0.4.4", "", { "dependencies": { "amdefine": ">=0.0.4" } }, "sha1-66T12pwNyZneaAMti092FzZSA2s="], + + "has-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "has-values/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "has-values/kind-of": ["kind-of@4.0.0", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-IIE989cSkosgc3hpGkUGb65y3Vc="], + + "heimdalljs-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "import-local/pkg-dir": ["pkg-dir@2.0.0", "", { "dependencies": { "find-up": "^2.1.0" } }, "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s="], + + "imports-loader/loader-utils": ["loader-utils@1.1.0", "", { "dependencies": { "big.js": "^3.1.3", "emojis-list": "^2.0.0", "json5": "^0.5.0" } }, "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0="], + + "imports-loader/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "inquirer/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "is-accessor-descriptor/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "is-builtin-module/builtin-modules": ["builtin-modules@2.0.0", "", {}, "sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg=="], + + "is-data-descriptor/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "is-descriptor/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "istanbul-api/istanbul-lib-source-maps": ["istanbul-lib-source-maps@1.2.5", "", { "dependencies": { "debug": "^3.1.0", "istanbul-lib-coverage": "^1.2.0", "mkdirp": "^0.5.1", "rimraf": "^2.6.1", "source-map": "^0.5.3" } }, "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA=="], + + "istanbul-api/js-yaml": ["js-yaml@3.12.0", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A=="], + + "jest-cli/yargs": ["yargs@10.1.2", "", { "dependencies": { "cliui": "^4.0.0", "decamelize": "^1.1.1", "find-up": "^2.1.0", "get-caller-file": "^1.0.1", "os-locale": "^2.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1", "yargs-parser": "^8.1.0" } }, "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig=="], + + "jest-haste-map/jest-docblock": ["jest-docblock@22.4.3", "", { "dependencies": { "detect-newline": "^2.1.0" } }, "sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg=="], + + "jest-jasmine2/source-map-support": ["source-map-support@0.5.6", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g=="], + + "jest-runner/jest-docblock": ["jest-docblock@22.4.3", "", { "dependencies": { "detect-newline": "^2.1.0" } }, "sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg=="], + + "jest-runtime/yargs": ["yargs@10.1.2", "", { "dependencies": { "cliui": "^4.0.0", "decamelize": "^1.1.1", "find-up": "^2.1.0", "get-caller-file": "^1.0.1", "os-locale": "^2.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1", "yargs-parser": "^8.1.0" } }, "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig=="], + + "jest-util/callsites": ["callsites@2.0.0", "", {}, "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="], + + "jest-util/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "jsdom/tough-cookie": ["tough-cookie@2.4.3", "", { "dependencies": { "psl": "^1.1.24", "punycode": "^1.4.1" } }, "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ=="], + + "jsinspect/babylon": ["babylon@6.16.1", "", {}, "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM="], + + "jsinspect/strip-json-comments": ["strip-json-comments@1.0.2", "", {}, "sha1-WkirlgI9usG3uND/q/b2PxZ3vp8="], + + "liftoff/findup-sync": ["findup-sync@2.0.0", "", { "dependencies": { "detect-file": "^1.0.0", "is-glob": "^3.1.0", "micromatch": "^3.0.4", "resolve-dir": "^1.0.1" } }, "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw="], + + "load-json-file/strip-bom": ["strip-bom@2.0.0", "", { "dependencies": { "is-utf8": "^0.2.0" } }, "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4="], + + "locate-path/path-exists": ["path-exists@3.0.0", "", {}, "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="], + + "loose-envify/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "make-iterator/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "matchdep/findup-sync": ["findup-sync@2.0.0", "", { "dependencies": { "detect-file": "^1.0.0", "is-glob": "^3.1.0", "micromatch": "^3.0.4", "resolve-dir": "^1.0.1" } }, "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw="], + + "matchdep/micromatch": ["micromatch@3.1.10", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="], + + "minipass/yallist": ["yallist@3.0.2", "", {}, "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k="], + + "mixin-deep/is-extendable": ["is-extendable@1.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4" } }, "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="], + + "mkdirp/minimist": ["minimist@0.0.8", "", {}, "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="], + + "nanomatch/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "nanomatch/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "nanomatch/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "needle/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "needle/iconv-lite": ["iconv-lite@0.4.23", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA=="], + + "node-libs-browser/browserify-zlib": ["browserify-zlib@0.2.0", "", { "dependencies": { "pako": "~1.0.5" } }, "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA=="], + + "normalize-package-data/is-builtin-module": ["is-builtin-module@1.0.0", "", { "dependencies": { "builtin-modules": "^1.0.0" } }, "sha1-VAVy0096wxGfj3bDDLwbHgN6/74="], + + "object-copy/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "object.defaults/for-own": ["for-own@1.0.0", "", { "dependencies": { "for-in": "^1.0.1" } }, "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs="], + + "object.map/for-own": ["for-own@1.0.0", "", { "dependencies": { "for-in": "^1.0.1" } }, "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs="], + + "object.reduce/for-own": ["for-own@1.0.0", "", { "dependencies": { "for-in": "^1.0.1" } }, "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs="], + + "opencollective/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="], + + "opencollective/inquirer": ["inquirer@3.0.6", "", { "dependencies": { "ansi-escapes": "^1.1.0", "chalk": "^1.0.0", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", "external-editor": "^2.0.1", "figures": "^2.0.0", "lodash": "^4.3.0", "mute-stream": "0.0.7", "run-async": "^2.2.0", "rx": "^4.1.0", "string-width": "^2.0.0", "strip-ansi": "^3.0.0", "through": "^2.3.6" } }, "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c="], + + "optimist/minimist": ["minimist@0.0.10", "", {}, "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="], + + "optimist/wordwrap": ["wordwrap@0.0.3", "", {}, "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="], + + "plugin-error/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "pumpify/pump": ["pump@2.0.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA=="], + + "randomatic/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "regjsparser/jsesc": ["jsesc@0.5.0", "", {}, "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="], + + "request-promise-native/tough-cookie": ["tough-cookie@2.4.3", "", { "dependencies": { "psl": "^1.1.24", "punycode": "^1.4.1" } }, "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ=="], + + "resolve-cwd/resolve-from": ["resolve-from@3.0.0", "", {}, "sha1-six699nWiBvItuZTM17rywoYh0g="], + + "sane/micromatch": ["micromatch@3.1.10", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="], + + "schema-utils/ajv": ["ajv@6.6.2", "", { "dependencies": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g=="], + + "schema-utils/ajv-keywords": ["ajv-keywords@3.2.0", "", {}, "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="], + + "set-value/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "snapdragon/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "snapdragon/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "snapdragon/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "snapdragon-node/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "static-extend/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "string-replace-loader/loader-utils": ["loader-utils@1.2.3", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^2.0.0", "json5": "^1.0.1" } }, "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA=="], + + "string-width/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "table/ajv": ["ajv@6.5.2", "", { "dependencies": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.1" } }, "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA=="], + + "table/ajv-keywords": ["ajv-keywords@3.2.0", "", {}, "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="], + + "table/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "tar/yallist": ["yallist@3.0.2", "", {}, "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k="], + + "temp/rimraf": ["rimraf@2.2.8", "", {}, "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI="], + + "test-exclude/micromatch": ["micromatch@3.1.10", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="], + + "to-regex-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "tr46/punycode": ["punycode@2.1.1", "", {}, "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="], + + "uglify-js/yargs": ["yargs@3.10.0", "", { "dependencies": { "camelcase": "^1.0.2", "cliui": "^2.1.0", "decamelize": "^1.0.0", "window-size": "0.1.0" } }, "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E="], + + "union-value/set-value": ["set-value@0.4.3", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.1", "to-object-path": "^0.3.0" } }, "sha1-fbCPnT0i3H945Trzw79GZuzfzPE="], + + "unset-value/has-value": ["has-value@0.3.1", "", { "dependencies": { "get-value": "^2.0.3", "has-values": "^0.1.4", "isobject": "^2.0.0" } }, "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8="], + + "uri-js/punycode": ["punycode@2.1.1", "", {}, "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="], + + "url/punycode": ["punycode@1.3.2", "", {}, "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="], + + "verror/extsprintf": ["extsprintf@1.4.0", "", {}, "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8="], + + "vinyl/replace-ext": ["replace-ext@1.0.0", "", {}, "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs="], + + "webpack/ajv": ["ajv@4.11.8", "", { "dependencies": { "co": "^4.6.0", "json-stable-stringify": "^1.0.1" } }, "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY="], + + "webpack-sources/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "whatwg-encoding/iconv-lite": ["iconv-lite@0.4.19", "", {}, "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="], + + "wide-align/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "wrap-ansi/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "yargs/camelcase": ["camelcase@3.0.0", "", {}, "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="], + + "yargs-parser/camelcase": ["camelcase@3.0.0", "", {}, "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="], + + "anymatch/micromatch/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "anymatch/micromatch/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "anymatch/micromatch/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], + + "anymatch/micromatch/extglob": ["extglob@2.0.4", "", { "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="], + + "anymatch/micromatch/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "assert/util/inherits": ["inherits@2.0.1", "", {}, "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="], + + "babel-code-frame/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="], + + "babel-code-frame/chalk/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "babel-code-frame/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="], + + "chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="], + + "chokidar/braces/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "chokidar/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "chokidar/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc="], + + "chokidar/is-glob/is-extglob": ["is-extglob@2.1.1", "", {}, "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="], + + "class-utils/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "cliui/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "commitizen/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="], + + "commitizen/chalk/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "commitizen/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="], + + "commitizen/inquirer/ansi-escapes": ["ansi-escapes@1.4.0", "", {}, "sha1-06ioOzGapneTZisT52HHkRQiMG4="], + + "commitizen/inquirer/cli-cursor": ["cli-cursor@1.0.2", "", { "dependencies": { "restore-cursor": "^1.0.1" } }, "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc="], + + "commitizen/inquirer/external-editor": ["external-editor@1.1.1", "", { "dependencies": { "extend": "^3.0.0", "spawn-sync": "^1.0.15", "tmp": "^0.0.29" } }, "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs="], + + "commitizen/inquirer/figures": ["figures@1.7.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5", "object-assign": "^4.1.0" } }, "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4="], + + "commitizen/inquirer/lodash": ["lodash@4.17.10", "", {}, "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="], + + "commitizen/inquirer/mute-stream": ["mute-stream@0.0.6", "", {}, "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s="], + + "commitizen/inquirer/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "eslint/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="], + + "eslint/chalk/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "eslint/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="], + + "eslint/inquirer/chalk": ["chalk@2.3.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ=="], + + "eslint/inquirer/external-editor": ["external-editor@2.2.0", "", { "dependencies": { "chardet": "^0.4.0", "iconv-lite": "^0.4.17", "tmp": "^0.0.33" } }, "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A=="], + + "eslint/inquirer/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "gauge/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "glob-parent/is-glob/is-extglob": ["is-extglob@2.1.1", "", {}, "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="], + + "gulp-cli/yargs/camelcase": ["camelcase@3.0.0", "", {}, "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="], + + "gulp-cli/yargs/yargs-parser": ["yargs-parser@5.0.0", "", { "dependencies": { "camelcase": "^3.0.0" } }, "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo="], + + "gulp-newer/plugin-error/arr-diff": ["arr-diff@1.1.0", "", { "dependencies": { "arr-flatten": "^1.0.1", "array-slice": "^0.2.3" } }, "sha1-aHwydYFjWI/vfeezb6vklesaOZo="], + + "gulp-newer/plugin-error/arr-union": ["arr-union@2.1.0", "", {}, "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0="], + + "gulp-newer/plugin-error/extend-shallow": ["extend-shallow@1.1.4", "", { "dependencies": { "kind-of": "^1.1.0" } }, "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE="], + + "gulp-plumber/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="], + + "gulp-plumber/chalk/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "gulp-plumber/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="], + + "gulp-plumber/plugin-error/arr-diff": ["arr-diff@1.1.0", "", { "dependencies": { "arr-flatten": "^1.0.1", "array-slice": "^0.2.3" } }, "sha1-aHwydYFjWI/vfeezb6vklesaOZo="], + + "gulp-plumber/plugin-error/arr-union": ["arr-union@2.1.0", "", {}, "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0="], + + "gulp-plumber/plugin-error/extend-shallow": ["extend-shallow@1.1.4", "", { "dependencies": { "kind-of": "^1.1.0" } }, "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE="], + + "has-values/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "import-local/pkg-dir/find-up": ["find-up@2.1.0", "", { "dependencies": { "locate-path": "^2.0.0" } }, "sha1-RdG35QbHF93UgndaK3eSCjwMV6c="], + + "inquirer/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "jest-cli/yargs/cliui": ["cliui@4.1.0", "", { "dependencies": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" } }, "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ=="], + + "jest-cli/yargs/find-up": ["find-up@2.1.0", "", { "dependencies": { "locate-path": "^2.0.0" } }, "sha1-RdG35QbHF93UgndaK3eSCjwMV6c="], + + "jest-cli/yargs/os-locale": ["os-locale@2.1.0", "", { "dependencies": { "execa": "^0.7.0", "lcid": "^1.0.0", "mem": "^1.1.0" } }, "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA=="], + + "jest-cli/yargs/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "jest-cli/yargs/which-module": ["which-module@2.0.0", "", {}, "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="], + + "jest-cli/yargs/yargs-parser": ["yargs-parser@8.1.0", "", { "dependencies": { "camelcase": "^4.1.0" } }, "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ=="], + + "jest-jasmine2/source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "jest-runtime/yargs/cliui": ["cliui@4.1.0", "", { "dependencies": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" } }, "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ=="], + + "jest-runtime/yargs/find-up": ["find-up@2.1.0", "", { "dependencies": { "locate-path": "^2.0.0" } }, "sha1-RdG35QbHF93UgndaK3eSCjwMV6c="], + + "jest-runtime/yargs/os-locale": ["os-locale@2.1.0", "", { "dependencies": { "execa": "^0.7.0", "lcid": "^1.0.0", "mem": "^1.1.0" } }, "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA=="], + + "jest-runtime/yargs/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "jest-runtime/yargs/which-module": ["which-module@2.0.0", "", {}, "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="], + + "jest-runtime/yargs/yargs-parser": ["yargs-parser@8.1.0", "", { "dependencies": { "camelcase": "^4.1.0" } }, "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ=="], + + "liftoff/findup-sync/detect-file": ["detect-file@1.0.0", "", {}, "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc="], + + "liftoff/findup-sync/is-glob": ["is-glob@3.1.0", "", { "dependencies": { "is-extglob": "^2.1.0" } }, "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo="], + + "liftoff/findup-sync/micromatch": ["micromatch@3.1.10", "", { "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", "braces": "^2.3.1", "define-property": "^2.0.2", "extend-shallow": "^3.0.2", "extglob": "^2.0.4", "fragment-cache": "^0.2.1", "kind-of": "^6.0.2", "nanomatch": "^1.2.9", "object.pick": "^1.3.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } }, "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="], + + "liftoff/findup-sync/resolve-dir": ["resolve-dir@1.0.1", "", { "dependencies": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" } }, "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M="], + + "matchdep/findup-sync/detect-file": ["detect-file@1.0.0", "", {}, "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc="], + + "matchdep/findup-sync/is-glob": ["is-glob@3.1.0", "", { "dependencies": { "is-extglob": "^2.1.0" } }, "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo="], + + "matchdep/findup-sync/resolve-dir": ["resolve-dir@1.0.1", "", { "dependencies": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" } }, "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M="], + + "matchdep/micromatch/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "matchdep/micromatch/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "matchdep/micromatch/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], + + "matchdep/micromatch/extglob": ["extglob@2.0.4", "", { "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="], + + "matchdep/micromatch/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "node-libs-browser/browserify-zlib/pako": ["pako@1.0.6", "", {}, "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="], + + "object-copy/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "opencollective/chalk/ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="], + + "opencollective/chalk/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "opencollective/chalk/supports-color": ["supports-color@2.0.0", "", {}, "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="], + + "opencollective/inquirer/ansi-escapes": ["ansi-escapes@1.4.0", "", {}, "sha1-06ioOzGapneTZisT52HHkRQiMG4="], + + "opencollective/inquirer/external-editor": ["external-editor@2.2.0", "", { "dependencies": { "chardet": "^0.4.0", "iconv-lite": "^0.4.17", "tmp": "^0.0.33" } }, "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A=="], + + "opencollective/inquirer/string-width": ["string-width@2.1.1", "", { "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" } }, "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="], + + "opencollective/inquirer/strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8="], + + "sane/micromatch/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "sane/micromatch/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "sane/micromatch/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], + + "sane/micromatch/extglob": ["extglob@2.0.4", "", { "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="], + + "sane/micromatch/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "schema-utils/ajv/fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="], + + "schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "snapdragon/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "static-extend/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "string-replace-loader/loader-utils/big.js": ["big.js@5.2.2", "", {}, "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="], + + "string-replace-loader/loader-utils/json5": ["json5@1.0.1", "", { "dependencies": { "minimist": "^1.2.0" } }, "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow=="], + + "string-width/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "table/ajv/fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="], + + "table/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "table/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "test-exclude/micromatch/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "test-exclude/micromatch/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "test-exclude/micromatch/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], + + "test-exclude/micromatch/extglob": ["extglob@2.0.4", "", { "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="], + + "test-exclude/micromatch/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "uglify-js/yargs/camelcase": ["camelcase@1.2.1", "", {}, "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="], + + "uglify-js/yargs/cliui": ["cliui@2.1.0", "", { "dependencies": { "center-align": "^0.1.1", "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE="], + + "union-value/set-value/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "unset-value/has-value/has-values": ["has-values@0.1.4", "", {}, "sha1-bWHeldkd/Km5oCCJrThL/49it3E="], + + "unset-value/has-value/isobject": ["isobject@2.1.0", "", { "dependencies": { "isarray": "1.0.0" } }, "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk="], + + "wide-align/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "anymatch/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "anymatch/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc="], + + "anymatch/micromatch/extglob/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "anymatch/micromatch/extglob/expand-brackets": ["expand-brackets@2.1.4", "", { "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha1-t3c14xXOMPa27/D4OwQVGiJEliI="], + + "anymatch/micromatch/extglob/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "babel-code-frame/chalk/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "chokidar/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "class-utils/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "class-utils/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "class-utils/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "commitizen/chalk/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "commitizen/inquirer/cli-cursor/restore-cursor": ["restore-cursor@1.0.1", "", { "dependencies": { "exit-hook": "^1.0.0", "onetime": "^1.0.0" } }, "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE="], + + "commitizen/inquirer/external-editor/tmp": ["tmp@0.0.29", "", { "dependencies": { "os-tmpdir": "~1.0.1" } }, "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA="], + + "commitizen/inquirer/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "eslint/chalk/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "eslint/inquirer/chalk/supports-color": ["supports-color@5.4.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w=="], + + "eslint/inquirer/external-editor/chardet": ["chardet@0.4.2", "", {}, "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="], + + "eslint/inquirer/external-editor/iconv-lite": ["iconv-lite@0.4.23", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA=="], + + "eslint/inquirer/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "gulp-newer/plugin-error/arr-diff/array-slice": ["array-slice@0.2.3", "", {}, "sha1-3Tz7gO15c6dRF82sabC5nshhhvU="], + + "gulp-newer/plugin-error/extend-shallow/kind-of": ["kind-of@1.1.0", "", {}, "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ="], + + "gulp-plumber/chalk/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "gulp-plumber/plugin-error/arr-diff/array-slice": ["array-slice@0.2.3", "", {}, "sha1-3Tz7gO15c6dRF82sabC5nshhhvU="], + + "gulp-plumber/plugin-error/extend-shallow/kind-of": ["kind-of@1.1.0", "", {}, "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ="], + + "jest-cli/yargs/os-locale/execa": ["execa@0.7.0", "", { "dependencies": { "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c="], + + "jest-cli/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "jest-runtime/yargs/os-locale/execa": ["execa@0.7.0", "", { "dependencies": { "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c="], + + "jest-runtime/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "liftoff/findup-sync/is-glob/is-extglob": ["is-extglob@2.1.1", "", {}, "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="], + + "liftoff/findup-sync/micromatch/arr-diff": ["arr-diff@4.0.0", "", {}, "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="], + + "liftoff/findup-sync/micromatch/array-unique": ["array-unique@0.3.2", "", {}, "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="], + + "liftoff/findup-sync/micromatch/braces": ["braces@2.3.2", "", { "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", "extend-shallow": "^2.0.1", "fill-range": "^4.0.0", "isobject": "^3.0.1", "repeat-element": "^1.1.2", "snapdragon": "^0.8.1", "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" } }, "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="], + + "liftoff/findup-sync/micromatch/extglob": ["extglob@2.0.4", "", { "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", "expand-brackets": "^2.1.4", "extend-shallow": "^2.0.1", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="], + + "liftoff/findup-sync/micromatch/kind-of": ["kind-of@6.0.2", "", {}, "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="], + + "liftoff/findup-sync/resolve-dir/expand-tilde": ["expand-tilde@2.0.2", "", { "dependencies": { "homedir-polyfill": "^1.0.1" } }, "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI="], + + "liftoff/findup-sync/resolve-dir/global-modules": ["global-modules@1.0.0", "", { "dependencies": { "global-prefix": "^1.0.1", "is-windows": "^1.0.1", "resolve-dir": "^1.0.0" } }, "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg=="], + + "matchdep/findup-sync/is-glob/is-extglob": ["is-extglob@2.1.1", "", {}, "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="], + + "matchdep/findup-sync/resolve-dir/expand-tilde": ["expand-tilde@2.0.2", "", { "dependencies": { "homedir-polyfill": "^1.0.1" } }, "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI="], + + "matchdep/findup-sync/resolve-dir/global-modules": ["global-modules@1.0.0", "", { "dependencies": { "global-prefix": "^1.0.1", "is-windows": "^1.0.1", "resolve-dir": "^1.0.0" } }, "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg=="], + + "matchdep/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "matchdep/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc="], + + "matchdep/micromatch/extglob/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "matchdep/micromatch/extglob/expand-brackets": ["expand-brackets@2.1.4", "", { "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha1-t3c14xXOMPa27/D4OwQVGiJEliI="], + + "matchdep/micromatch/extglob/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "object-copy/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "object-copy/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "object-copy/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "opencollective/chalk/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "opencollective/inquirer/external-editor/chardet": ["chardet@0.4.2", "", {}, "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="], + + "opencollective/inquirer/external-editor/iconv-lite": ["iconv-lite@0.4.23", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA=="], + + "opencollective/inquirer/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="], + + "opencollective/inquirer/string-width/strip-ansi": ["strip-ansi@4.0.0", "", { "dependencies": { "ansi-regex": "^3.0.0" } }, "sha1-qEeQIusaw2iocTibY1JixQXuNo8="], + + "opencollective/inquirer/strip-ansi/ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="], + + "sane/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "sane/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc="], + + "sane/micromatch/extglob/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "sane/micromatch/extglob/expand-brackets": ["expand-brackets@2.1.4", "", { "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha1-t3c14xXOMPa27/D4OwQVGiJEliI="], + + "sane/micromatch/extglob/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "snapdragon/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "snapdragon/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "snapdragon/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "static-extend/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "static-extend/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "static-extend/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "test-exclude/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "test-exclude/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc="], + + "test-exclude/micromatch/extglob/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "test-exclude/micromatch/extglob/expand-brackets": ["expand-brackets@2.1.4", "", { "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha1-t3c14xXOMPa27/D4OwQVGiJEliI="], + + "test-exclude/micromatch/extglob/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "uglify-js/yargs/cliui/wordwrap": ["wordwrap@0.0.2", "", {}, "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="], + + "anymatch/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "anymatch/micromatch/extglob/expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "anymatch/micromatch/extglob/expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "class-utils/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "class-utils/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "commitizen/inquirer/cli-cursor/restore-cursor/onetime": ["onetime@1.1.0", "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789", {}, "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="], + + "eslint/inquirer/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="], + + "jest-cli/yargs/os-locale/execa/get-stream": ["get-stream@3.0.0", "", {}, "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="], + + "jest-runtime/yargs/os-locale/execa/get-stream": ["get-stream@3.0.0", "", {}, "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="], + + "liftoff/findup-sync/micromatch/braces/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "liftoff/findup-sync/micromatch/braces/fill-range": ["fill-range@4.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" } }, "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc="], + + "liftoff/findup-sync/micromatch/extglob/define-property": ["define-property@1.0.0", "", { "dependencies": { "is-descriptor": "^1.0.0" } }, "sha1-dp66rz9KY6rTr56NMEybvnm/sOY="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets": ["expand-brackets@2.1.4", "", { "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", "extend-shallow": "^2.0.1", "posix-character-classes": "^0.1.0", "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" } }, "sha1-t3c14xXOMPa27/D4OwQVGiJEliI="], + + "liftoff/findup-sync/micromatch/extglob/extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8="], + + "liftoff/findup-sync/resolve-dir/global-modules/global-prefix": ["global-prefix@1.0.2", "", { "dependencies": { "expand-tilde": "^2.0.2", "homedir-polyfill": "^1.0.1", "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" } }, "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4="], + + "matchdep/findup-sync/resolve-dir/global-modules/global-prefix": ["global-prefix@1.0.2", "", { "dependencies": { "expand-tilde": "^2.0.2", "homedir-polyfill": "^1.0.1", "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" } }, "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4="], + + "matchdep/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "matchdep/micromatch/extglob/expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "matchdep/micromatch/extglob/expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "object-copy/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "object-copy/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "sane/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "sane/micromatch/extglob/expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "sane/micromatch/extglob/expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "snapdragon/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "snapdragon/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "static-extend/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "static-extend/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "test-exclude/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "test-exclude/micromatch/extglob/expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "anymatch/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "anymatch/micromatch/extglob/expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "liftoff/findup-sync/micromatch/braces/fill-range/is-number": ["is-number@3.0.0", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property": ["define-property@0.2.5", "", { "dependencies": { "is-descriptor": "^0.1.0" } }, "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY="], + + "matchdep/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "matchdep/micromatch/extglob/expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "sane/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "sane/micromatch/extglob/expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "test-exclude/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "anymatch/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "anymatch/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "anymatch/micromatch/extglob/expand-brackets/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "liftoff/findup-sync/micromatch/braces/fill-range/is-number/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property/is-descriptor": ["is-descriptor@0.1.6", "", { "dependencies": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", "kind-of": "^5.0.0" } }, "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="], + + "matchdep/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "matchdep/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "matchdep/micromatch/extglob/expand-brackets/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "sane/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "sane/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "sane/micromatch/extglob/expand-brackets/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "anymatch/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "anymatch/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor": ["is-accessor-descriptor@0.1.6", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor": ["is-data-descriptor@0.1.4", "", { "dependencies": { "kind-of": "^3.0.2" } }, "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property/is-descriptor/kind-of": ["kind-of@5.1.0", "", {}, "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="], + + "matchdep/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "matchdep/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "sane/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "sane/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "test-exclude/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-accessor-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + + "liftoff/findup-sync/micromatch/extglob/expand-brackets/define-property/is-descriptor/is-data-descriptor/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ="], + } +} +" +`; + +exports[`bun pm migrate for existing yarn.lock yarn-lock-mkdirp: yarn-lock-mkdirp 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "dependencies": { + "mkdirp": "^1.0.2", + }, + }, + }, + "packages": { + "mkdirp": ["mkdirp@1.0.4", "", {}, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + } +} +" +`; + +exports[`bun pm migrate for existing yarn.lock yarn-lock-mkdirp-file-dep: yarn-lock-mkdirp-file-dep 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "dependencies": { + "mkdirp": "file:mkdirp", + }, + }, + }, + "packages": { + "mkdirp": ["mkdirp@file:mkdirp", {}], + } +} +" +`; + +exports[`bun pm migrate for existing yarn.lock yarn-lock-mkdirp-no-resolved: yarn-lock-mkdirp-no-resolved 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "dependencies": { + "mkdirp": "^1.0.2", + }, + }, + }, + "packages": { + "mkdirp": ["mkdirp@1.0.4", "", {}, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + } +} +" +`; + +exports[`bun pm migrate for existing yarn.lock yarn-stuff: yarn-stuff 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "a", + "dependencies": { + "abbrev": "^1.1.1", + "full-git-url": "git+https://github.com/isaacs/abbrev-js.git", + "ghshort": "github:isaacs/abbrev-js", + "old": "npm:abbrev@1.0.x", + "pinned": "npm:abbrev@1.1.1", + "reg": "npm:abbrev@^1.1.1", + "remote": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "symlink": "file:./abbrev-link-target", + "tarball": "file:abbrev-1.1.1.tgz", + }, + }, + }, + "packages": { + "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "full-git-url": ["abbrev-js@github:isaacs/abbrev-js#3f9802e", {}, ""], + + "ghshort": ["ghshort@3.0.1", "https://codeload.github.com/isaacs/abbrev-js/tar.gz/3f9802e56ff878761a338e43ecacbfed39d2181d", {}, ""], + + "old": ["abbrev@1.0.9", "", {}, "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q=="], + + "pinned": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "reg": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "remote": ["abbrev@https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8", {}], + + "symlink": ["symlink@file:./abbrev-link-target", {}], + + "tarball": ["tarball@abbrev-1.1.1.tgz", {}], + } +} +" +`; + +exports[`bun pm migrate for existing yarn.lock yarn-stuff/abbrev-link-target: yarn-stuff/abbrev-link-target 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "abbrev", + }, + }, + "packages": {} +} +" +`; diff --git a/test/cli/install/migration/yarn-lock-migration.test.ts b/test/cli/install/migration/yarn-lock-migration.test.ts new file mode 100644 index 0000000000..738f8e7898 --- /dev/null +++ b/test/cli/install/migration/yarn-lock-migration.test.ts @@ -0,0 +1,1201 @@ +import { describe, expect, test } from "bun:test"; +import fs from "fs"; +import { bunEnv, bunExe, tempDirWithFiles } from "harness"; +import { join } from "path"; + +describe("yarn.lock migration basic", () => { + test("simple yarn.lock migration produces correct bun.lock", async () => { + const tempDir = tempDirWithFiles("yarn-migration-simple", { + "package.json": JSON.stringify( + { + name: "simple-test", + version: "1.0.0", + dependencies: { + "is-number": "^7.0.0", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(migrateResult.stdout).text(), + new Response(migrateResult.stderr).text(), + migrateResult.exited, + ]); + + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("simple-yarn-migration"); + }); + + test("complex yarn.lock with multiple dependencies and versions", async () => { + const tempDir = tempDirWithFiles("yarn-migration-complex", { + "package.json": JSON.stringify( + { + name: "complex-test", + version: "1.0.0", + dependencies: { + "express": "^4.18.2", + "lodash": "^4.17.21", + }, + devDependencies: { + "jest": "^29.0.0", + "typescript": "^5.0.0", + }, + optionalDependencies: { + "fsevents": "^2.3.2", + }, + peerDependencies: { + "react": "^18.0.0", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +express@^4.18.2: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== + dependencies: + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +has-property-descriptors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== + dependencies: + get-intrinsic "^1.2.2" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzBkH31s2EbTbs6iVFEJElQzL5aORl2ATXXJaOmXa2w= + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +jest@^29.0.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +react@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typescript@^5.0.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(migrateResult.stdout).text(), + new Response(migrateResult.stderr).text(), + migrateResult.exited, + ]); + + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("complex-yarn-migration"); + }); + + test("yarn.lock with npm aliases", async () => { + const tempDir = tempDirWithFiles("yarn-migration-aliases", { + "package.json": JSON.stringify( + { + name: "alias-test", + version: "1.0.0", + dependencies: { + "@types/bun": "npm:bun-types@1.2.19", + "my-lodash": "npm:lodash@4.17.21", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/bun@npm:bun-types@1.2.19": + version "1.2.19" + resolved "https://registry.yarnpkg.com/bun-types/-/bun-types-1.2.19.tgz#0cecd78ed08bae389cc902ae3a5617c390b0fab6" + integrity sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "20.11.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e" + integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w== + dependencies: + undici-types "~5.26.4" + +lodash@4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +my-lodash@npm:lodash@4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(migrateResult.stdout).text(), + new Response(migrateResult.stderr).text(), + migrateResult.exited, + ]); + + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("aliases-yarn-migration"); + + // Verify that npm aliases are handled correctly + expect(bunLockContent).toContain('"@types/bun": ["bun-types@1.2.19"'); + expect(bunLockContent).toContain('"my-lodash": ["lodash@4.17.21"'); + }); + + test("yarn.lock with resolutions", async () => { + const tempDir = tempDirWithFiles("yarn-migration-resolutions", { + "package.json": JSON.stringify( + { + name: "resolutions-test", + version: "1.0.0", + dependencies: { + "webpack": "^5.89.0", + }, + resolutions: { + "acorn": "8.11.3", + "webpack/acorn": "8.11.2", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +acorn@8.11.2: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + +acorn@8.11.3, acorn@^8.7.1, acorn@^8.8.2: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +webpack@^5.89.0: + version "5.89.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.89.0.tgz#56b8bf9a34356e93a6625770006490bf3a7f32dc" + integrity sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" + acorn "^8.7.1" + acorn-import-assertions "^1.9.0" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.7" + watchpack "^2.4.0" + webpack-sources "^3.2.3" +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(migrateResult.stdout).text(), + new Response(migrateResult.stderr).text(), + migrateResult.exited, + ]); + + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("resolutions-yarn-migration"); + + // Verify resolutions are handled + expect(bunLockContent).toContain("resolutions"); + }); + + test("yarn.lock with workspace dependencies", async () => { + const tempDir = tempDirWithFiles("yarn-migration-workspace", { + "package.json": JSON.stringify( + { + name: "workspace-root", + version: "1.0.0", + private: true, + workspaces: ["packages/*"], + dependencies: { + "lodash": "^4.17.21", + }, + }, + null, + 2, + ), + "packages/a/package.json": JSON.stringify( + { + name: "@workspace/a", + version: "1.0.0", + dependencies: { + "@workspace/b": "workspace:*", + "is-number": "^7.0.0", + }, + }, + null, + 2, + ), + "packages/b/package.json": JSON.stringify( + { + name: "@workspace/b", + version: "1.0.0", + dependencies: { + "is-odd": "^3.0.1", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@workspace/b@workspace:*", "@workspace/b@workspace:packages/b": + version "0.0.0-use.local" + resolved "file:packages/b" + dependencies: + is-odd "^3.0.1" + +is-number@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-6.0.0.tgz#e6d15ad31fc262887d1846d1c6c84c9b3b0b5982" + integrity sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-odd@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-3.0.1.tgz#65101baf63c59f7b5c3a429d0a4e3d8ca7914559" + integrity sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA== + dependencies: + is-number "^6.0.0" + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(migrateResult.stdout).text(), + new Response(migrateResult.stderr).text(), + migrateResult.exited, + ]); + + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("workspace-yarn-migration"); + + // TODO: Workspace dependencies are not yet supported in yarn migration + // expect(bunLockContent).toContain("workspace:"); + }); + + test("yarn.lock with scoped packages and parent/child relationships", async () => { + const tempDir = tempDirWithFiles("yarn-migration-scoped", { + "package.json": JSON.stringify( + { + name: "scoped-test", + version: "1.0.0", + dependencies: { + "@babel/core": "^7.23.7", + "babel-loader": "^9.1.3", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" + integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.7" + "@babel/parser" "^7.23.6" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.7" + "@babel/types" "^7.23.6" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +babel-loader@^9.1.3: + version "9.1.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" + integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== + dependencies: + find-cache-dir "^4.0.0" + schema-utils "^4.0.0" + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +babel-loader/chalk@^2.4.2: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(migrateResult.stdout).text(), + new Response(migrateResult.stderr).text(), + migrateResult.exited, + ]); + + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("scoped-yarn-migration"); + + // Verify scoped packages are at the bottom + const lines = bunLockContent.split("\n"); + const packageSectionStart = lines.findIndex(line => line.trim().startsWith("packages:")); + const lastBabelIndex = lines.findLastIndex(line => line.includes("@babel/")); + const firstNonScopedAfterPackages = lines.findIndex( + (line, idx) => idx > packageSectionStart && line.includes('"') && !line.includes("/") && !line.includes("@"), + ); + + // Scoped packages should appear after non-scoped ones + if (firstNonScopedAfterPackages !== -1) { + expect(lastBabelIndex).toBeGreaterThan(firstNonScopedAfterPackages); + } + }); + + test("migration with realistic complex yarn.lock", async () => { + // Create a realistic yarn.lock with various edge cases + const tempDir = tempDirWithFiles("yarn-migration-complex-realistic", { + "package.json": JSON.stringify( + { + name: "complex-app", + version: "1.0.0", + dependencies: { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@babel/core": "^7.20.0", + "webpack": "^5.75.0", + }, + devDependencies: { + "@types/react": "^18.0.0", + "typescript": "^4.9.0", + "eslint": "^8.0.0", + }, + peerDependencies: { + "react": ">=16.8.0", + }, + optionalDependencies: { + "fsevents": "^2.3.2", + }, + }, + null, + 2, + ), + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/core@^7.20.0": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7f12f7fe01cfcc5c4f37fa6e09a6e7ac0736b5e9" + integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.11" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.12" + "@babel/types" "^7.20.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + +"@types/react@^18.0.0": + version "18.0.28" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" + integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +eslint@^8.0.0: + version "8.35.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" + integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== + dependencies: + "@eslint/eslintrc" "^2.0.0" + "@eslint/js" "8.35.0" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.4.0" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +fsevents@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +typescript@^4.9.0: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +webpack@^5.75.0: + version "5.76.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" + integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.7.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.4.0" + webpack-sources "^3.2.3" +`, + }); + + // Run bun pm migrate + const migrateResult = await Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + const exitCode = await migrateResult.exited; + expect(exitCode).toBe(0); + expect(fs.existsSync(join(tempDir, "bun.lock"))).toBe(true); + + const bunLockContent = fs.readFileSync(join(tempDir, "bun.lock"), "utf8"); + expect(bunLockContent).toMatchSnapshot("complex-realistic-yarn-migration"); + + // Verify key features are migrated + expect(bunLockContent).toContain('"react": ['); + expect(bunLockContent).toContain('"@babel/core": ['); + expect(bunLockContent).toContain('"webpack": ['); + expect(bunLockContent).toContain('"typescript": ['); + + // Verify peer dependencies are captured + expect(bunLockContent).toContain("peerDependencies"); + }); +}); + +describe("bun pm migrate for existing yarn.lock", () => { + const folders = [ + "yarn-cli-repo", + "yarn-lock-mkdirp", + "yarn-lock-mkdirp-file-dep", + "yarn-lock-mkdirp-no-resolved", + "yarn-stuff", + "yarn-stuff/abbrev-link-target", + ]; + test.each(folders)("%s", async folder => { + const packageJsonContent = await Bun.file(join(import.meta.dir, "yarn", folder, "package.json")).text(); + const yarnLockContent = await Bun.file(join(import.meta.dir, "yarn", folder, "yarn.lock")).text(); + + const tempDir = tempDirWithFiles("yarn-lock-migration-", { + "package.json": packageJsonContent, + "yarn.lock": yarnLockContent, + }); + + const migrateResult = Bun.spawn({ + cmd: [bunExe(), "pm", "migrate", "-f"], + cwd: tempDir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + }); + + expect(migrateResult.exited).resolves.toBe(0); + expect(Bun.file(join(tempDir, "bun.lock")).exists()).resolves.toBe(true); + + const bunLockContent = await Bun.file(join(tempDir, "bun.lock")).text(); + expect(bunLockContent).toMatchSnapshot(folder); + }); +}); diff --git a/test/cli/install/migration/yarn/.gitignore b/test/cli/install/migration/yarn/.gitignore new file mode 100644 index 0000000000..c47977a32f --- /dev/null +++ b/test/cli/install/migration/yarn/.gitignore @@ -0,0 +1,2 @@ +# we do need it the files here +!yarn.lock diff --git a/test/cli/install/migration/yarn/yarn-cli-repo/package.json b/test/cli/install/migration/yarn/yarn-cli-repo/package.json new file mode 100644 index 0000000000..0f45abf503 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-cli-repo/package.json @@ -0,0 +1,157 @@ +{ + "name": "yarn", + "installationMethod": "unknown", + "version": "1.23.0-0", + "license": "BSD-2-Clause", + "preferGlobal": true, + "description": "📦🐈 Fast, reliable, and secure dependency management.", + "dependencies": { + "@zkochan/cmd-shim": "^3.1.0", + "babel-runtime": "^6.26.0", + "bytes": "^3.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.1.0", + "cli-table3": "^0.4.0", + "commander": "^2.9.0", + "death": "^1.0.0", + "debug": "^3.0.0", + "deep-equal": "^1.0.1", + "detect-indent": "^5.0.0", + "dnscache": "^1.0.1", + "glob": "^7.1.1", + "gunzip-maybe": "^1.4.0", + "hash-for-dep": "^1.2.3", + "imports-loader": "^0.8.0", + "ini": "^1.3.4", + "inquirer": "^6.2.0", + "invariant": "^2.2.0", + "is-builtin-module": "^2.0.0", + "is-ci": "^1.0.10", + "is-webpack-bundle": "^1.0.0", + "js-yaml": "^3.13.1", + "leven": "^2.0.0", + "loud-rejection": "^1.2.0", + "micromatch": "^2.3.11", + "mkdirp": "^0.5.1", + "node-emoji": "^1.6.1", + "normalize-url": "^2.0.0", + "npm-logical-tree": "^1.2.1", + "object-path": "^0.11.2", + "proper-lockfile": "^2.0.0", + "puka": "^1.0.0", + "read": "^1.0.7", + "request": "^2.87.0", + "request-capture-har": "^1.2.2", + "rimraf": "^2.5.0", + "semver": "^5.1.0", + "ssri": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-bom": "^3.0.0", + "tar-fs": "^1.16.0", + "tar-stream": "^1.6.1", + "uuid": "^3.0.1", + "v8-compile-cache": "^2.0.0", + "validate-npm-package-license": "^3.0.4", + "yn": "^2.0.0" + }, + "devDependencies": { + "babel-core": "^6.26.0", + "babel-eslint": "^7.2.3", + "babel-loader": "^6.2.5", + "babel-plugin-array-includes": "^2.0.3", + "babel-plugin-inline-import": "^3.0.0", + "babel-plugin-transform-builtin-extend": "^1.1.2", + "babel-plugin-transform-inline-imports-commonjs": "^1.0.0", + "babel-plugin-transform-runtime": "^6.4.3", + "babel-preset-env": "^1.6.0", + "babel-preset-flow": "^6.23.0", + "babel-preset-stage-0": "^6.0.0", + "babylon": "^6.5.0", + "commitizen": "^2.9.6", + "cz-conventional-changelog": "^2.0.0", + "eslint": "^4.3.0", + "eslint-config-fb-strict": "^22.0.0", + "eslint-plugin-babel": "^5.0.0", + "eslint-plugin-flowtype": "^2.35.0", + "eslint-plugin-jasmine": "^2.6.2", + "eslint-plugin-jest": "^21.0.0", + "eslint-plugin-jsx-a11y": "^6.0.2", + "eslint-plugin-prefer-object-spread": "^1.2.1", + "eslint-plugin-prettier": "^2.1.2", + "eslint-plugin-react": "^7.1.0", + "eslint-plugin-relay": "^0.0.28", + "eslint-plugin-yarn-internal": "file:scripts/eslint-rules", + "execa": "^0.11.0", + "fancy-log": "^1.3.2", + "flow-bin": "^0.66.0", + "git-release-notes": "^3.0.0", + "gulp": "^4.0.0", + "gulp-babel": "^7.0.0", + "gulp-if": "^2.0.1", + "gulp-newer": "^1.0.0", + "gulp-plumber": "^1.0.1", + "gulp-sourcemaps": "^2.2.0", + "jest": "^22.4.4", + "jsinspect": "^0.12.6", + "minimatch": "^3.0.4", + "mock-stdin": "^0.3.0", + "prettier": "^1.5.2", + "string-replace-loader": "^2.1.1", + "temp": "^0.8.3", + "webpack": "^2.1.0-beta.25", + "yargs": "^6.3.0" + }, + "resolutions": { + "sshpk": "^1.14.2" + }, + "engines": { + "node": ">=4.0.0" + }, + "repository": "yarnpkg/yarn", + "bin": { + "yarn": "./bin/yarn.js", + "yarnpkg": "./bin/yarn.js" + }, + "scripts": { + "build": "gulp build", + "build-bundle": "node ./scripts/build-webpack.js", + "build-chocolatey": "powershell ./scripts/build-chocolatey.ps1", + "build-deb": "./scripts/build-deb.sh", + "build-dist": "bash ./scripts/build-dist.sh", + "build-win-installer": "scripts\\build-windows-installer.bat", + "changelog": "git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md", + "dupe-check": "yarn jsinspect ./src", + "lint": "eslint . && flow check", + "pkg-tests": "yarn --cwd packages/pkg-tests jest yarn.test.js", + "prettier": "eslint src __tests__ --fix", + "release-branch": "./scripts/release-branch.sh", + "test": "yarn lint && yarn test-only", + "test-only": "node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose", + "test-only-debug": "node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose", + "test-coverage": "node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose", + "watch": "gulp watch", + "commit": "git-cz" + }, + "jest": { + "collectCoverageFrom": [ + "src/**/*.js" + ], + "testEnvironment": "node", + "modulePathIgnorePatterns": [ + "__tests__/fixtures/", + "packages/pkg-tests/pkg-tests-fixtures", + "dist/" + ], + "testPathIgnorePatterns": [ + "__tests__/(fixtures|__mocks__)/", + "updates/", + "_(temp|mock|install|init|helpers).js$", + "packages/pkg-tests" + ] + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } + } +} diff --git a/test/cli/install/migration/yarn/yarn-cli-repo/yarn.lock b/test/cli/install/migration/yarn/yarn-cli-repo/yarn.lock new file mode 100644 index 0000000000..6d113fe6a4 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-cli-repo/yarn.lock @@ -0,0 +1,7925 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0-beta.35": + version "7.0.0-beta.55" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.55.tgz#71f530e7b010af5eb7a7df7752f78921dd57e9ee" + integrity sha1-cfUw57AQr163p993UveJId1X6e4= + dependencies: + "@babel/highlight" "7.0.0-beta.55" + +"@babel/highlight@7.0.0-beta.55": + version "7.0.0-beta.55" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.55.tgz#988653647d629c261dae156e74d5f0252ba520c0" + integrity sha1-mIZTZH1inCYdrhVudNXwJSulIMA= + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@gulp-sourcemaps/identity-map@1.X": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz#1e6fe5d8027b1f285dc0d31762f566bccd73d5a9" + integrity sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ== + dependencies: + acorn "^5.0.3" + css "^2.2.1" + normalize-path "^2.1.1" + source-map "^0.6.0" + through2 "^2.0.3" + +"@gulp-sourcemaps/map-sources@1.X": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" + integrity sha1-iQrnxdjId/bThIYCFazp1+yUW9o= + dependencies: + normalize-path "^2.0.1" + through2 "^2.0.3" + +"@zkochan/cmd-shim@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" + integrity sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg== + dependencies: + is-windows "^1.0.0" + mkdirp-promise "^5.0.1" + mz "^2.5.0" + +abab@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" + integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= + +abab@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" + integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-dynamic-import@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" + integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= + dependencies: + acorn "^4.0.3" + +acorn-globals@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" + integrity sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ== + dependencies: + acorn "^5.0.0" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= + dependencies: + acorn "^3.0.4" + +acorn@5.X, acorn@^5.0.0, acorn@^5.0.3, acorn@^5.5.0, acorn@^5.5.3: + version "5.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + integrity sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ== + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +acorn@^4.0.3: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= + +ajv-keywords@^1.1.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= + +ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" + integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= + +ajv@^4.7.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.1.0, ajv@^5.2.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ajv@^6.0.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" + integrity sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.1" + +ajv@^6.1.0: + version "6.6.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" + integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + +ansi-colors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" + integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== + dependencies: + ansi-wrap "^0.1.0" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + dependencies: + ansi-wrap "0.1.0" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= + +ansi-escapes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-wrap@0.1.0, ansi-wrap@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +append-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" + integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + dependencies: + buffer-equal "^1.0.0" + +append-transform@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" + integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== + dependencies: + default-require-extensions "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +aria-query@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" + integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= + dependencies: + ast-types-flow "0.0.7" + commander "^2.11.0" + +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-filter@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" + integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= + dependencies: + make-iterator "^1.0.0" + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-map@^2.0.0, arr-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" + integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= + dependencies: + make-iterator "^1.0.0" + +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-each@^1.0.0, array-each@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= + +array-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" + integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +array-initial@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" + integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= + dependencies: + array-slice "^1.0.0" + is-number "^4.0.0" + +array-last@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" + integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== + dependencies: + is-number "^4.0.0" + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= + +array-slice@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== + +array-sort@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" + integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== + dependencies: + default-compare "^1.0.0" + get-value "^2.0.6" + kind-of "^5.0.2" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asap@~2.0.3: + version "2.0.6" + 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== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + dependencies: + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-types-flow@0.0.7, ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-done@^1.2.0, async-done@^1.2.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.1.tgz#14b7b73667b864c8f02b5b253fc9c6eddb777f3e" + integrity sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.2" + process-nextick-args "^1.0.7" + stream-exhaust "^1.0.1" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +async-settle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" + integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= + dependencies: + async-done "^1.2.2" + +async@^1.4.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@^2.1.2, async@^2.1.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== + dependencies: + lodash "^4.17.10" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + integrity sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w== + +axobject-query@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.1.tgz#05dfa705ada8ad9db993fa6896f22d395b0b0a07" + integrity sha1-Bd+nBa2orZ25k/polvItOVsLCgc= + dependencies: + ast-types-flow "0.0.7" + +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.0, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-eslint@^7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827" + integrity sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc= + dependencies: + babel-code-frame "^6.22.0" + babel-traverse "^6.23.1" + babel-types "^6.23.0" + babylon "^6.17.0" + +babel-generator@^6.18.0, babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-bindify-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" + integrity sha1-FMGeXxQte0fxmlJDHlKxzLxAozA= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +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" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-explode-class@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" + integrity sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes= + dependencies: + babel-helper-bindify-decorators "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-jest@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-22.4.4.tgz#977259240420e227444ebe49e226a61e49ea659d" + integrity sha512-A9NB6/lZhYyypR9ATryOSDcqBaqNdzq4U+CN+/wcMsLcmKkPxQEoTKLajGfd3IkxNyVBT8NewUK2nWyGbSzHEQ== + dependencies: + babel-plugin-istanbul "^4.1.5" + babel-preset-jest "^22.4.4" + +babel-loader@^6.2.5: + version "6.4.1" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca" + integrity sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo= + dependencies: + find-cache-dir "^0.1.1" + loader-utils "^0.2.16" + mkdirp "^0.5.1" + object-assign "^4.0.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-array-includes@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/babel-plugin-array-includes/-/babel-plugin-array-includes-2.0.3.tgz#cf5452e81c7b803fb7959f1045ac88e2ec28ff76" + integrity sha1-z1RS6Bx7gD+3lZ8QRayI4uwo/3Y= + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-inline-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-inline-import/-/babel-plugin-inline-import-3.0.0.tgz#220eb2a52f8e779d8fb89447f950275e1e3f5981" + integrity sha512-thnykl4FMb8QjMjVCuZoUmAM7r2mnTn5qJwrryCvDv6rugbJlTHZMctdjDtEgD0WBAXJOLJSGXN3loooEwx7UQ== + dependencies: + require-resolve "0.0.2" + +babel-plugin-istanbul@^4.1.5: + version "4.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" + integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ== + dependencies: + babel-plugin-syntax-object-rest-spread "^6.13.0" + find-up "^2.1.0" + istanbul-lib-instrument "^1.10.1" + test-exclude "^4.2.1" + +babel-plugin-jest-hoist@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.4.tgz#b9851906eab34c7bf6f8c895a2b08bea1a844c0b" + integrity sha512-DUvGfYaAIlkdnygVIEl0O4Av69NtuQWcrjMOv6DODPuhuGLDnbsARz3AwiiI/EkIMMlxQDUcrZ9yoyJvTNjcVQ== + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + integrity sha1-a8lj67FuzLrmuStZbrfzXDQqi5o= + +babel-plugin-syntax-class-constructor-call@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" + integrity sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY= + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= + +babel-plugin-syntax-decorators@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + integrity sha1-MSVjtNvePMgGzuPkFszurd0RrAs= + +babel-plugin-syntax-do-expressions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" + integrity sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0= + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= + +babel-plugin-syntax-export-extensions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" + integrity sha1-cKFITw+QiaToStRLrDU8lbmxJyE= + +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" + integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0= + +babel-plugin-syntax-function-bind@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46" + integrity sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y= + +babel-plugin-syntax-object-rest-spread@^6.13.0, 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" + integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-async-generator-functions@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + integrity sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-builtin-extend@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-builtin-extend/-/babel-plugin-transform-builtin-extend-1.1.2.tgz#5e96fecf58b8fa1ed74efcad88475b2af3c9116e" + integrity sha1-Xpb+z1i4+h7XTvytiEdbKvPJEW4= + dependencies: + babel-runtime "^6.2.0" + babel-template "^6.3.0" + +babel-plugin-transform-class-constructor-call@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9" + integrity sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk= + dependencies: + babel-plugin-syntax-class-constructor-call "^6.18.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-class-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" + integrity sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0= + dependencies: + babel-helper-explode-class "^6.24.1" + babel-plugin-syntax-decorators "^6.13.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-do-expressions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb" + integrity sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs= + dependencies: + babel-plugin-syntax-do-expressions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-export-extensions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" + integrity sha1-U3OLR+deghhYnuqUbLvTkQm75lM= + dependencies: + babel-plugin-syntax-export-extensions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + integrity sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988= + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-function-bind@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97" + integrity sha1-xvuOlqwpajELjPjqQBRiQH3fapc= + dependencies: + babel-plugin-syntax-function-bind "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-inline-imports-commonjs@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-imports-commonjs/-/babel-plugin-transform-inline-imports-commonjs-1.2.0.tgz#20c7d192bafc54c8727386e3387d8ee4ef19e6a5" + integrity sha1-IMfRkrr8VMhyc4bjOH2O5O8Z5qU= + dependencies: + babel-plugin-transform-strict-mode "^6.8.0" + builtin-modules "^1.1.1" + +babel-plugin-transform-object-rest-spread@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-runtime@^6.4.3: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee" + integrity sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-strict-mode@^6.24.1, babel-plugin-transform-strict-mode@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-polyfill@6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" + integrity sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0= + dependencies: + babel-runtime "^6.22.0" + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-preset-env@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + integrity sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0= + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-jest@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-22.4.4.tgz#ec9fbd8bcd7dfd24b8b5320e0e688013235b7c39" + integrity sha512-+dxMtOFwnSYWfum0NaEc0O03oSdwBsjx4tMSChRDPGwu/4wSY6Q6ANW3wkjKpJzzguaovRs/DODcT4hbSN8yiA== + dependencies: + babel-plugin-jest-hoist "^22.4.4" + babel-plugin-syntax-object-rest-spread "^6.13.0" + +babel-preset-stage-0@^6.0.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz#5642d15042f91384d7e5af8bc88b1db95b039e6a" + integrity sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo= + dependencies: + babel-plugin-transform-do-expressions "^6.22.0" + babel-plugin-transform-function-bind "^6.22.0" + babel-preset-stage-1 "^6.24.1" + +babel-preset-stage-1@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0" + integrity sha1-dpLNfc1oSZB+auSgqFWJz7niv7A= + dependencies: + babel-plugin-transform-class-constructor-call "^6.24.1" + babel-plugin-transform-export-extensions "^6.22.0" + babel-preset-stage-2 "^6.24.1" + +babel-preset-stage-2@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" + integrity sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE= + dependencies: + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-transform-class-properties "^6.24.1" + babel-plugin-transform-decorators "^6.24.1" + babel-preset-stage-3 "^6.24.1" + +babel-preset-stage-3@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" + integrity sha1-g2raCp56f6N8sTj7kyb4eTSkg5U= + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-generator-functions "^6.24.1" + babel-plugin-transform-async-to-generator "^6.24.1" + babel-plugin-transform-exponentiation-operator "^6.24.1" + babel-plugin-transform-object-rest-spread "^6.22.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@6.16.1: + version "6.16.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" + integrity sha1-MMWiL0gZeKnn+M399JaxHZS0BNM= + +babylon@^6.17.0, babylon@^6.18.0, babylon@^6.5.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +bach@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" + integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= + dependencies: + arr-filter "^1.1.1" + arr-flatten "^1.0.1" + arr-map "^2.0.0" + array-each "^1.0.0" + array-initial "^1.0.0" + array-last "^1.1.1" + async-done "^1.2.2" + async-settle "^1.0.0" + now-and-later "^2.0.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU= + +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +broccoli-kitchen-sink-helpers@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/broccoli-kitchen-sink-helpers/-/broccoli-kitchen-sink-helpers-0.3.1.tgz#77c7c18194b9664163ec4fcee2793444926e0c06" + integrity sha1-d8fBgZS5ZkFj7E/O4nk0RJJuDAY= + dependencies: + glob "^5.0.10" + mkdirp "^0.5.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-process-hrtime@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" + integrity sha1-Ql1opY00R/AqBKqJQYf86K+Le44= + +browser-resolve@^1.11.2: + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" + integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== + dependencies: + resolve "1.1.7" + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^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= + dependencies: + bn.js "^4.1.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" + +browserify-zlib@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + integrity sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0= + dependencies: + pako "~0.2.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +bser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" + integrity sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk= + dependencies: + node-int64 "^0.4.0" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= + +builtin-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" + integrity sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg== + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cachedir@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-1.3.0.tgz#5e01928bf2d95b5edd94b0942188246740e0dbc4" + integrity sha512-O1ji32oyON9laVPJL1IZ5bmwd2cB46VfpxkDequezH+15FDzzVddEyrGEeX4WusDSqKxdyFdDQDEG1yo1GoWkg== + dependencies: + os-homedir "^1.0.1" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +caniuse-lite@^1.0.30000844: + version "1.0.30000865" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz#70026616e8afe6e1442f8bb4e1092987d81a2f25" + integrity sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw== + +capture-exit@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" + integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28= + dependencies: + rsvp "^3.3.3" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +chokidar@^2.0.0, chokidar@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" + integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + lodash.debounce "^4.0.8" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.5" + optionalDependencies: + fsevents "^1.2.2" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE= + +ci-info@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" + integrity sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= + dependencies: + restore-cursor "^1.0.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-table3@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.4.0.tgz#a7fd50f011d734e3f16403cfcbedbea97659e417" + integrity sha512-o0slI6EFJNI2aKE9jG1bVN6jXJG2vjzYsGhyd9RqRV/YiiEmzSwNNXb5qJmfLDSOdvfA6sUvdKVvi3p3Y1apxA== + dependencies: + kind-of "^3.0.4" + object-assign "^4.1.0" + string-width "^1.0.1" + optionalDependencies: + colors "^1.1.2" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +cloneable-readable@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" + integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-map@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" + integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= + dependencies: + arr-map "^2.0.2" + for-own "^1.0.0" + make-iterator "^1.0.0" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + integrity sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg== + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + integrity sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok= + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +colors@^1.1.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" + integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== + +combined-stream@1.0.6, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= + dependencies: + delayed-stream "~1.0.0" + +commander@^2.11.0, commander@^2.9.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" + integrity sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew== + +commitizen@^2.9.6: + version "2.10.1" + resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-2.10.1.tgz#8c395def34a895f4e94952c2efc3c9eb4c3683bd" + integrity sha1-jDld7zSolfTpSVLC78PJ60w2g70= + dependencies: + cachedir "^1.1.0" + chalk "1.1.3" + cz-conventional-changelog "2.0.0" + dedent "0.6.0" + detect-indent "4.0.0" + find-node-modules "1.0.4" + find-root "1.0.0" + fs-extra "^1.0.0" + glob "7.1.1" + inquirer "1.2.3" + lodash "4.17.5" + minimist "1.2.0" + opencollective "1.0.3" + path-exists "2.1.0" + shelljs "0.7.6" + strip-json-comments "2.0.1" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +compare-versions@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.3.0.tgz#af93ea705a96943f622ab309578b9b90586f39c3" + integrity sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ== + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.4.7, concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +conventional-commit-types@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/conventional-commit-types/-/conventional-commit-types-2.2.0.tgz#5db95739d6c212acbe7b6f656a11b940baa68946" + integrity sha1-XblXOdbCEqy+e29lahG5QLqmiUY= + +convert-source-map@1.X, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU= + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +copy-props@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" + integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== + dependencies: + each-props "^1.3.0" + is-plain-object "^2.0.1" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + 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== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^5.0.1, cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +css@2.X, css@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.3.tgz#f861f4ba61e79bedc962aa548e5780fd95cbc6be" + integrity sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ== + dependencies: + inherits "^2.0.1" + source-map "^0.1.38" + source-map-resolve "^0.5.1" + urix "^0.1.0" + +cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797" + integrity sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog== + +cssstyle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.0.0.tgz#79b16d51ec5591faec60e688891f15d2a5705129" + integrity sha512-Bpuh47j2mRMY60X90mXaJAEtJwxvA2roZzbgwAXYhMbmwmakdRr4Cq9L5SkleKJNLOKqHIa2YWyOXDX3VgggSQ== + dependencies: + cssom "0.3.x" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +cz-conventional-changelog@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-2.0.0.tgz#55a979afdfe95e7024879d2a0f5924630170b533" + integrity sha1-Val5r9/pXnAkh50qD1kkYwFwtTM= + dependencies: + conventional-commit-types "^2.0.0" + lodash.map "^4.5.1" + longest "^1.0.1" + pad-right "^0.2.2" + right-pad "^1.0.1" + word-wrap "^1.0.3" + +cz-conventional-changelog@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-2.1.0.tgz#2f4bc7390e3244e4df293e6ba351e4c740a7c764" + integrity sha1-L0vHOQ4yROTfKT5ro1Hkx0Cnx2Q= + dependencies: + conventional-commit-types "^2.0.0" + lodash.map "^4.5.1" + longest "^1.0.1" + right-pad "^1.0.1" + word-wrap "^1.0.3" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= + dependencies: + es5-ext "^0.10.9" + +damerau-levenshtein@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" + integrity sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.0.tgz#24802de4e81c298ea8a9388bb0d8e461c774684f" + integrity sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA== + dependencies: + abab "^1.0.4" + whatwg-mimetype "^2.0.0" + whatwg-url "^6.4.0" + +date-fns@^1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + integrity sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw== + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= + +death@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= + +debug-fabulous@1.X: + version "1.1.0" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz#af8a08632465224ef4174a9f06308c3c2a1ebc8e" + integrity sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg== + dependencies: + debug "3.X" + memoizee "0.4.X" + object-assign "4.X" + +debug@3.X, debug@^3.0.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^1.0.0, decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +dedent@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb" + integrity sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s= + +deep-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +default-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" + integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== + dependencies: + kind-of "^5.0.2" + +default-require-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" + integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= + dependencies: + strip-bom "^3.0.0" + +default-resolution@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" + integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + integrity sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ= + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-file@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63" + integrity sha1-STXe39lIhkjgBrASlWbpOGcR6mM= + dependencies: + fs-exists-sync "^0.1.0" + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +detect-indent@4.0.0, detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + dependencies: + repeating "^2.0.0" + +detect-indent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +detect-newline@2.X, detect-newline@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= + +diff@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dnscache@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dnscache/-/dnscache-1.0.1.tgz#42cb2b9bfb5e8fbdfa395aac74e127fc05074d31" + integrity sha1-Qssrm/tej736OVqsdOEn/AUHTTE= + dependencies: + asap "~2.0.3" + lodash.clone "~4.3.2" + +doctrine@^2.0.0, doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + +duplexify@^3.5.0, duplexify@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" + integrity sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +each-props@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" + integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== + dependencies: + is-plain-object "^2.0.1" + object.defaults "^1.1.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ejs@^2.5.7: + version "2.6.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" + integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== + +electron-to-chromium@^1.3.47: + version "1.3.55" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.55.tgz#f150e10b20b77d9d41afcca312efe0c3b1a7fdce" + integrity sha1-8VDhCyC3fZ1Br8yjEu/gw7Gn/c4= + +elliptic@^6.0.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emoji-regex@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" + integrity sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ== + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + 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" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^3.3.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" + integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + object-assign "^4.0.1" + tapable "^0.2.7" + +errno@^0.1.3: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.5.1, es-abstract@^1.7.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + integrity sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0= + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: + version "0.10.45" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.45.tgz#0bfdf7b473da5919d5adf3bd25ceb754fccc3653" + integrity sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + next-tick "1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escodegen@^1.9.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" + integrity sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-fb-strict@^22.0.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/eslint-config-fb-strict/-/eslint-config-fb-strict-22.4.3.tgz#ceca0283d1025ca6a93b8ea99d0052ad20c49f6b" + integrity sha512-xGH75nMO69RqDU96KCI/wh58Y3Ej+xLl/zdK5uQKfvf2DRcwRw1JgArCR+9P0SzWIgEzPPEGVxpRPjYW3XfI+w== + dependencies: + eslint-config-fbjs "^2.0.1" + +eslint-config-fbjs@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-fbjs/-/eslint-config-fbjs-2.0.1.tgz#395896fd740e0e28dc1c2072e3bc982e88247df5" + integrity sha512-nZ/JByixNK/8epeQqmrtNCYYMXCjHoPkJwHaHg4aZyZlS62YLttDSWYE6ISGl070V+o6dkFbDALceWaO3Po+Sw== + +eslint-plugin-babel@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.1.0.tgz#9c76e476162041e50b6ba69aa4eae3bdd6a4e1c3" + integrity sha512-HBkv9Q0LU/IhNUauC8TrbhcN79Yq/+xh2bYTOcv6KMaV2tsvVphkHwDTJ9r3C6mJUnmxrtzT3DQfrWj0rOISqQ== + dependencies: + eslint-rule-composer "^0.3.0" + +eslint-plugin-flowtype@^2.35.0: + version "2.50.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.0.tgz#953e262fa9b5d0fa76e178604892cf60dfb916da" + integrity sha512-10FnBXCp8odYcpUFXGAh+Zko7py0hUWutTd3BN/R9riukH360qNPLYPR3/xV9eu9K7OJDjJrsflBnL6RwxFnlw== + dependencies: + lodash "^4.17.10" + +eslint-plugin-jasmine@^2.6.2: + version "2.10.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.10.1.tgz#5733b709e751f4bc40e31e1c16989bd2cdfbec97" + integrity sha1-VzO3CedR9LxA4x4cFpib0s377Jc= + +eslint-plugin-jest@^21.0.0: + version "21.18.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-21.18.0.tgz#d7305969a9c1902f895468791d968fcf08b5c0b7" + integrity sha512-fhuJuehoMtuEQ3Klgx0629hDmbs0M0g4tSZ65Wq2NqpLWCK5UC7hQnGS1Wh4+Vc/9P4ss4HxqZ1XK7honqUZNg== + +eslint-plugin-jsx-a11y@^6.0.2: + version "6.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.1.tgz#7bf56dbe7d47d811d14dbb3ddff644aa656ce8e1" + integrity sha512-JsxNKqa3TwmPypeXNnI75FntkUktGzI1wSa1LgNZdSOMI+B4sxnr1lSF8m8lPiz4mKiC+14ysZQM4scewUrP7A== + dependencies: + aria-query "^3.0.0" + array-includes "^3.0.3" + ast-types-flow "^0.0.7" + axobject-query "^2.0.1" + damerau-levenshtein "^1.0.4" + emoji-regex "^6.5.1" + has "^1.0.3" + jsx-ast-utils "^2.0.1" + +eslint-plugin-prefer-object-spread@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz#27fb91853690cceb3ae6101d9c8aecc6a67a402c" + integrity sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw= + +eslint-plugin-prettier@^2.1.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz#71998c60aedfa2141f7bfcbf9d1c459bf98b4fad" + integrity sha512-tGek5clmW5swrAx1mdPYM8oThrBE83ePh7LeseZHBWfHVGrHPhKn7Y5zgRMbU/9D5Td9K4CEmUPjGxA7iw98Og== + dependencies: + fast-diff "^1.1.1" + jest-docblock "^21.0.0" + +eslint-plugin-react@^7.1.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz#af5c1fef31c4704db02098f9be18202993828b50" + integrity sha512-18rzWn4AtbSUxFKKM7aCVcj5LXOhOKdwBino3KKWy4psxfPW0YtIbE8WNRDUdyHFL50BeLb6qFd4vpvNYyp7hw== + dependencies: + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.0.1" + prop-types "^15.6.2" + +eslint-plugin-relay@^0.0.28: + version "0.0.28" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-0.0.28.tgz#dd9ba7dc03fd21f3a30e053d21d90e5bf2ecff34" + integrity sha512-CvyT/WxEQmcUKE4lVqjxgioTj3zSvHnT9bvR4cISgs9j2z4J5Ojsurjcv/kWe4I6gf6L+lV6zcVuZ2LkiRIO6g== + dependencies: + graphql "^14.0.0" + +"eslint-plugin-yarn-internal@file:scripts/eslint-rules": + version "0.0.0" + +eslint-rule-composer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== + +eslint-scope@^3.7.1: + version "3.7.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" + integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.3.0.tgz#fcd7c96376bbf34c85ee67ed0012a299642b108f" + integrity sha1-/NfJY3a780yF7mftABKimWQrEI8= + dependencies: + ajv "^5.2.0" + babel-code-frame "^6.22.0" + chalk "^1.1.3" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^2.6.8" + doctrine "^2.0.0" + eslint-scope "^3.7.1" + espree "^3.4.3" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^9.17.0" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.8.4" + json-stable-stringify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^4.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-json-comments "~2.0.1" + table "^4.0.1" + text-table "~0.2.0" + +espree@^3.4.3: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + +events@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +exec-sh@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" + integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== + dependencies: + merge "^1.2.0" + +execa@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.11.0.tgz#0b3c71daf9b9159c252a863cd981af1b4410d97a" + integrity sha512-k5AR22vCt1DcfeiRixW46U5tMLtBg44ssdJM9PiXw3D8Bn5qyxFCSnKY/eR22y+ctFDGPqafpaXg2G4Emyua4A== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + +expand-tilde@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" + integrity sha1-C4HrqJflo9MdHD0QL48BRB5VlEk= + dependencies: + os-homedir "^1.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +expect@^22.4.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/expect/-/expect-22.4.3.tgz#d5a29d0a0e1fb2153557caef2674d4547e914674" + integrity sha512-XcNXEPehqn8b/jm8FYotdX0YrXn36qp4HWlrVT4ktwQas1l1LPxiVWncYnnL2eyMtKAmVIaG0XAp0QlrqJaxaA== + dependencies: + ansi-styles "^3.2.0" + jest-diff "^22.4.3" + jest-get-type "^22.4.3" + jest-matcher-utils "^22.4.3" + jest-message-util "^22.4.3" + jest-regex-util "^22.4.3" + +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= + dependencies: + kind-of "^1.1.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@^3.0.0, extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-1.1.1.tgz#12d7b0db850f7ff7e7081baf4005700060c4600b" + integrity sha1-Etew24UPf/fnCBuvQAVwAGDEYAs= + dependencies: + extend "^3.0.0" + spawn-sync "^1.0.15" + tmp "^0.0.29" + +external-editor@^2.0.1, external-editor@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +external-editor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fancy-log@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + integrity sha1-9BEl49hPLn2JpD0G2VjI94vha+E= + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + time-stamp "^1.0.0" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-diff@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" + integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fb-watchman@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" + integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= + dependencies: + bser "^2.0.0" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + +filepaths@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/filepaths/-/filepaths-0.3.0.tgz#a1c9a4601b6eae7fb876fc1ac98479ceb557c177" + integrity sha1-ocmkYBturn+4dvwayYR5zrVXwXc= + +fileset@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" + integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA= + dependencies: + glob "^7.0.3" + minimatch "^3.0.3" + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + integrity sha1-yN765XyKUqinhPnjHFfHQumToLk= + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-node-modules@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/find-node-modules/-/find-node-modules-1.0.4.tgz#b6deb3cccb699c87037677bcede2c5f5862b2550" + integrity sha1-tt6zzMtpnIcDdne87eLF9YYrJVA= + dependencies: + findup-sync "0.4.2" + merge "^1.2.0" + +find-root@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.0.0.tgz#962ff211aab25c6520feeeb8d6287f8f6e95807a" + integrity sha1-li/yEaqyXGUg/u641ih/j26VgHo= + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +findup-sync@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.2.tgz#a8117d0f73124f5a4546839579fe52d7129fb5e5" + integrity sha1-qBF9D3MST1pFRoOVef5S1xKfteU= + dependencies: + detect-file "^0.1.0" + is-glob "^2.0.1" + micromatch "^2.3.7" + resolve-dir "^0.1.0" + +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +fined@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" + integrity sha1-s33IRLdqL15wgeiE98CuNE8VNHY= + dependencies: + expand-tilde "^2.0.2" + is-plain-object "^2.0.3" + object.defaults "^1.1.0" + object.pick "^1.2.0" + parse-filepath "^1.0.1" + +flagged-respawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" + integrity sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c= + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +flow-bin@^0.66.0: + version "0.66.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.66.0.tgz#a96dde7015dc3343fd552a7b4963c02be705ca26" + integrity sha1-qW3ecBXcM0P9VSp7SWPAK+cFyiY= + +flush-write-stream@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" + integrity sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.4" + +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +fork-stream@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" + integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA= + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= + +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + integrity sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== + dependencies: + minipass "^2.2.1" + +fs-mkdirp-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + dependencies: + graceful-fs "^4.1.11" + through2 "^2.0.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.2, fsevents@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.0.0.tgz#9e074cb898bd2b9ebabb445a1766d7f43576d977" + integrity sha512-FneLKMENeOR7wOK0/ZXCh+lwqtnPwkeunJjRN28LPqzGvNAhYvrTAhXv6xDm4vsJ0M7lcRbIYHQudKsSy2RtSQ== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +git-release-notes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/git-release-notes/-/git-release-notes-3.0.0.tgz#3d8b1afcd2ebe0dd3f9449dc2a7106be4b7de5d3" + integrity sha512-FvaIV55dE03hXmD+yUB3ZLyxoiDQZetYw53hX7EPOfr3u+caIIXyUiGilJB+4fF7IjglE4YBY8O4gl3wsviFQA== + dependencies: + date-fns "^1.29.0" + debug "^3.1.0" + ejs "^2.5.7" + optimist "^0.6.1" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-stream@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + dependencies: + extend "^3.0.0" + glob "^7.1.1" + glob-parent "^3.1.0" + is-negated-glob "^1.0.0" + ordered-read-streams "^1.0.0" + pumpify "^1.3.5" + readable-stream "^2.1.5" + remove-trailing-separator "^1.0.1" + to-absolute-glob "^2.0.0" + unique-stream "^2.0.2" + +glob-watcher@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.1.tgz#239aaa621b6bd843b288fdf6b155f50963c7d7ea" + integrity sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g== + dependencies: + async-done "^1.2.0" + chokidar "^2.0.0" + just-debounce "^1.0.0" + object.defaults "^1.1.0" + +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.10: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" + integrity sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0= + dependencies: + global-prefix "^0.1.4" + is-windows "^0.2.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" + integrity sha1-jTvGuNo8qBEqFg2NSW/wRiv+948= + dependencies: + homedir-polyfill "^1.0.0" + ini "^1.3.4" + is-windows "^0.2.0" + which "^1.2.12" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +globals@^9.17.0, globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +glogg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" + integrity sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw== + dependencies: + sparkles "^1.0.0" + +graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= + +graphql@^14.0.0: + version "14.0.2" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650" + integrity sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw== + dependencies: + iterall "^1.2.2" + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + +gulp-babel@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-7.0.1.tgz#b9c8e29fa376b36c57989db820fc1c1715bb47cb" + integrity sha512-UqHS3AdxZyJCRxqnAX603Dj3k/Wx6hzcgmav3QcxvsIFq3Y8ZkU7iXd0O+JwD5ivqCc6o0r1S7tCB/xxLnuSNw== + dependencies: + plugin-error "^1.0.1" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-cli@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.0.1.tgz#7847e220cb3662f2be8a6d572bf14e17be5a994b" + integrity sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ== + dependencies: + ansi-colors "^1.0.1" + archy "^1.0.0" + array-sort "^1.0.0" + color-support "^1.1.3" + concat-stream "^1.6.0" + copy-props "^2.0.1" + fancy-log "^1.3.2" + gulplog "^1.0.0" + interpret "^1.1.0" + isobject "^3.0.1" + liftoff "^2.5.0" + matchdep "^2.0.0" + mute-stdout "^1.0.0" + pretty-hrtime "^1.0.0" + replace-homedir "^1.0.0" + semver-greatest-satisfied-range "^1.1.0" + v8flags "^3.0.1" + yargs "^7.1.0" + +gulp-if@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-2.0.2.tgz#a497b7e7573005041caa2bc8b7dda3c80444d629" + integrity sha1-pJe351cwBQQcqivIt92jyARE1ik= + dependencies: + gulp-match "^1.0.3" + ternary-stream "^2.0.1" + through2 "^2.0.1" + +gulp-match@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.0.3.tgz#91c7c0d7f29becd6606d57d80a7f8776a87aba8e" + integrity sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4= + dependencies: + minimatch "^3.0.3" + +gulp-newer@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/gulp-newer/-/gulp-newer-1.4.0.tgz#25243ed6eac8f5462b95894e0d41937b112e65f3" + integrity sha512-h79fGO55S/P9eAADbLAP9aTtVYpLSR1ONj08VPaSdVVNVYhTS8p1CO1TW7kEMu+hC+sytmCqcUr5LesvZEtDoQ== + dependencies: + glob "^7.0.3" + kew "^0.7.0" + plugin-error "^0.1.2" + +gulp-plumber@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gulp-plumber/-/gulp-plumber-1.2.0.tgz#18ea03912c9ee483f8a5499973b5954cd90f6ad8" + integrity sha512-L/LJftsbKoHbVj6dN5pvMsyJn9jYI0wT0nMg3G6VZhDac4NesezecYTi8/48rHi+yEic3sUpw6jlSc7qNWh32A== + dependencies: + chalk "^1.1.3" + fancy-log "^1.3.2" + plugin-error "^0.1.2" + through2 "^2.0.3" + +gulp-sourcemaps@^2.2.0: + version "2.6.4" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz#cbb2008450b1bcce6cd23bf98337be751bf6e30a" + integrity sha1-y7IAhFCxvM5s0jv5gze+dRv24wo= + dependencies: + "@gulp-sourcemaps/identity-map" "1.X" + "@gulp-sourcemaps/map-sources" "1.X" + acorn "5.X" + convert-source-map "1.X" + css "2.X" + debug-fabulous "1.X" + detect-newline "2.X" + graceful-fs "4.X" + source-map "~0.6.0" + strip-bom-string "1.X" + through2 "2.X" + +gulp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.0.tgz#95766c601dade4a77ed3e7b2b6dc03881b596366" + integrity sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y= + dependencies: + glob-watcher "^5.0.0" + gulp-cli "^2.0.0" + undertaker "^1.0.0" + vinyl-fs "^3.0.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= + dependencies: + glogg "^1.0.0" + +gunzip-maybe@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/gunzip-maybe/-/gunzip-maybe-1.4.1.tgz#39c72ed89d1b49ba708e18776500488902a52027" + integrity sha512-qtutIKMthNJJgeHQS7kZ9FqDq59/Wn0G2HYCRNjpup7yKfVI6/eqwpmroyZGFoCYaG+sW6psNVb4zoLADHpp2g== + dependencies: + browserify-zlib "^0.1.4" + is-deflate "^1.0.0" + is-gzip "^1.0.0" + peek-stream "^1.1.0" + pumpify "^1.3.3" + through2 "^2.0.3" + +handlebars@^4.0.3: + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" + integrity sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw= + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash-for-dep@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/hash-for-dep/-/hash-for-dep-1.2.3.tgz#5ec69fca32c23523972d52acb5bb65ffc3664cab" + integrity sha512-NE//rDaCFpWHViw30YM78OAGBShU+g4dnUGY3UWGyEzPOGYg/ptOjk32nEc+bC1xz+RfK5UIs6lOL6eQdrV4Ow== + dependencies: + broccoli-kitchen-sink-helpers "^0.3.1" + heimdalljs "^0.2.3" + heimdalljs-logger "^0.1.7" + resolve "^1.4.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" + integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +heimdalljs-logger@^0.1.7: + version "0.1.9" + resolved "https://registry.yarnpkg.com/heimdalljs-logger/-/heimdalljs-logger-0.1.9.tgz#d76ada4e45b7bb6f786fc9c010a68eb2e2faf176" + integrity sha1-12raTkW3u294b8nAEKaOsuL68XY= + dependencies: + debug "^2.2.0" + heimdalljs "^0.2.0" + +heimdalljs@^0.2.0, heimdalljs@^0.2.3: + version "0.2.5" + resolved "https://registry.yarnpkg.com/heimdalljs/-/heimdalljs-0.2.5.tgz#6aa54308eee793b642cff9cf94781445f37730ac" + integrity sha1-aqVDCO7nk7ZCz/nPlHgURfN3MKw= + dependencies: + rsvp "~3.2.1" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= + dependencies: + parse-passwd "^1.0.0" + +hosted-git-info@^2.1.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + +html-encoding-sniffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" + integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== + dependencies: + whatwg-encoding "^1.0.1" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +iconv-lite@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== + +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" + integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + dependencies: + minimatch "^3.0.4" + +ignore@^3.3.3: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +import-local@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" + integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ== + dependencies: + pkg-dir "^2.0.0" + resolve-cwd "^2.0.0" + +imports-loader@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.8.0.tgz#030ea51b8ca05977c40a3abfd9b4088fe0be9a69" + integrity sha512-kXWL7Scp8KQ4552ZcdVTeaQCZSLW+e6nJfp3cwUMB673T7Hr98Xjx5JK+ql7ADlJUvj1JS5O01RLbKoutN5QDQ== + dependencies: + loader-utils "^1.0.2" + source-map "^0.6.1" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +ini@^1.3.4, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +inquirer@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-1.2.3.tgz#4dec6f32f37ef7bb0b2ed3f1d1a5c3f545074918" + integrity sha1-TexvMvN+97sLLtPx0aXD9UUHSRg= + dependencies: + ansi-escapes "^1.1.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + external-editor "^1.1.0" + figures "^1.3.5" + lodash "^4.3.0" + mute-stream "0.0.6" + pinkie-promise "^2.0.0" + run-async "^2.2.0" + rx "^4.1.0" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +inquirer@3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" + integrity sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c= + dependencies: + ansi-escapes "^1.1.0" + chalk "^1.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.1" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx "^4.1.0" + string-width "^2.0.0" + strip-ansi "^3.0.0" + through "^2.3.6" + +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +inquirer@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" + integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.0" + figures "^2.0.0" + lodash "^4.17.10" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.1.0" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +interpret@^1.0.0, interpret@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= + +invariant@^2.2.0, invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= + dependencies: + builtin-modules "^1.0.0" + +is-builtin-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-2.0.0.tgz#431104b3b4ba838ec7a17d82bb3bccd2233e8cd9" + integrity sha512-G2jLHphOywpgrL/AaJKWDXpdpGR9X4V1PCkB+EwG5Z28z8EukgdWnAUFAS2wdBtIpwHhHBIiq0NBOWEbSXN0Rg== + dependencies: + builtin-modules "^2.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-ci@^1.0.10: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" + integrity sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg== + dependencies: + ci-info "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-deflate@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14" + integrity sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ= + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-generator-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" + integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go= + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= + dependencies: + is-extglob "^2.1.1" + +is-gzip@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83" + integrity sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM= + +is-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= + +is-path-in-cwd@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + +is-promise@^2.1, is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +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" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + integrity sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI= + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-utf8@^0.2.0, is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + +is-webpack-bundle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-webpack-bundle/-/is-webpack-bundle-1.0.0.tgz#576a50bb7c53d1d6a5c1647939c93ae2cbb90eea" + integrity sha1-V2pQu3xT0dalwWR5Ock64su5Duo= + +is-windows@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" + integrity sha1-3hqm1j6indJIc3tp8f+LgALSEIw= + +is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +istanbul-api@^1.1.14: + version "1.3.1" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.1.tgz#4c3b05d18c0016d1022e079b98dc82c40f488954" + integrity sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g== + dependencies: + async "^2.1.4" + compare-versions "^3.1.0" + fileset "^2.0.2" + istanbul-lib-coverage "^1.2.0" + istanbul-lib-hook "^1.2.0" + istanbul-lib-instrument "^1.10.1" + istanbul-lib-report "^1.1.4" + istanbul-lib-source-maps "^1.2.4" + istanbul-reports "^1.3.0" + js-yaml "^3.7.0" + mkdirp "^0.5.1" + once "^1.4.0" + +istanbul-lib-coverage@^1.1.1, istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" + integrity sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A== + +istanbul-lib-hook@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz#f614ec45287b2a8fc4f07f5660af787575601805" + integrity sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg== + dependencies: + append-transform "^1.0.0" + +istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.8.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b" + integrity sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ== + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.18.0" + istanbul-lib-coverage "^1.2.0" + semver "^5.3.0" + +istanbul-lib-report@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz#e886cdf505c4ebbd8e099e4396a90d0a28e2acb5" + integrity sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA== + dependencies: + istanbul-lib-coverage "^1.2.0" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz#20fb54b14e14b3fb6edb6aca3571fd2143db44e6" + integrity sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA== + dependencies: + debug "^3.1.0" + istanbul-lib-coverage "^1.1.2" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + +istanbul-lib-source-maps@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1" + integrity sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA== + dependencies: + debug "^3.1.0" + istanbul-lib-coverage "^1.2.0" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + +istanbul-reports@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.3.0.tgz#2f322e81e1d9520767597dca3c20a0cce89a3554" + integrity sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA== + dependencies: + handlebars "^4.0.3" + +iterall@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" + integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== + +jest-changed-files@^22.2.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-22.4.3.tgz#8882181e022c38bd46a2e4d18d44d19d90a90fb2" + integrity sha512-83Dh0w1aSkUNFhy5d2dvqWxi/y6weDwVVLU6vmK0cV9VpRxPzhTeGimbsbRDSnEoszhF937M4sDLLeS7Cu/Tmw== + dependencies: + throat "^4.0.0" + +jest-cli@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-22.4.4.tgz#68cd2a2aae983adb1e6638248ca21082fd6d9e90" + integrity sha512-I9dsgkeyjVEEZj9wrGrqlH+8OlNob9Iptyl+6L5+ToOLJmHm4JwOPatin1b2Bzp5R5YRQJ+oiedx7o1H7wJzhA== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.1" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.1.11" + import-local "^1.0.0" + is-ci "^1.0.10" + istanbul-api "^1.1.14" + istanbul-lib-coverage "^1.1.1" + istanbul-lib-instrument "^1.8.0" + istanbul-lib-source-maps "^1.2.1" + jest-changed-files "^22.2.0" + jest-config "^22.4.4" + jest-environment-jsdom "^22.4.1" + jest-get-type "^22.1.0" + jest-haste-map "^22.4.2" + jest-message-util "^22.4.0" + jest-regex-util "^22.1.0" + jest-resolve-dependencies "^22.1.0" + jest-runner "^22.4.4" + jest-runtime "^22.4.4" + jest-snapshot "^22.4.0" + jest-util "^22.4.1" + jest-validate "^22.4.4" + jest-worker "^22.2.2" + micromatch "^2.3.11" + node-notifier "^5.2.1" + realpath-native "^1.0.0" + rimraf "^2.5.4" + slash "^1.0.0" + string-length "^2.0.0" + strip-ansi "^4.0.0" + which "^1.2.12" + yargs "^10.0.3" + +jest-config@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-22.4.4.tgz#72a521188720597169cd8b4ff86934ef5752d86a" + integrity sha512-9CKfo1GC4zrXSoMLcNeDvQBfgtqGTB1uP8iDIZ97oB26RCUb886KkKWhVcpyxVDOUxbhN+uzcBCeFe7w+Iem4A== + dependencies: + chalk "^2.0.1" + glob "^7.1.1" + jest-environment-jsdom "^22.4.1" + jest-environment-node "^22.4.1" + jest-get-type "^22.1.0" + jest-jasmine2 "^22.4.4" + jest-regex-util "^22.1.0" + jest-resolve "^22.4.2" + jest-util "^22.4.1" + jest-validate "^22.4.4" + pretty-format "^22.4.0" + +jest-diff@^22.4.0, jest-diff@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-22.4.3.tgz#e18cc3feff0aeef159d02310f2686d4065378030" + integrity sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA== + dependencies: + chalk "^2.0.1" + diff "^3.2.0" + jest-get-type "^22.4.3" + pretty-format "^22.4.3" + +jest-docblock@^21.0.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== + +jest-docblock@^22.4.0, jest-docblock@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.4.3.tgz#50886f132b42b280c903c592373bb6e93bb68b19" + integrity sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg== + dependencies: + detect-newline "^2.1.0" + +jest-environment-jsdom@^22.4.1: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz#d67daa4155e33516aecdd35afd82d4abf0fa8a1e" + integrity sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w== + dependencies: + jest-mock "^22.4.3" + jest-util "^22.4.3" + jsdom "^11.5.1" + +jest-environment-node@^22.4.1: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-22.4.3.tgz#54c4eaa374c83dd52a9da8759be14ebe1d0b9129" + integrity sha512-reZl8XF6t/lMEuPWwo9OLfttyC26A5AMgDyEQ6DBgZuyfyeNUzYT8BFo6uxCCP/Av/b7eb9fTi3sIHFPBzmlRA== + dependencies: + jest-mock "^22.4.3" + jest-util "^22.4.3" + +jest-get-type@^22.1.0, jest-get-type@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" + integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== + +jest-haste-map@^22.4.2: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-22.4.3.tgz#25842fa2ba350200767ac27f658d58b9d5c2e20b" + integrity sha512-4Q9fjzuPVwnaqGKDpIsCSoTSnG3cteyk2oNVjBX12HHOaF1oxql+uUiqZb5Ndu7g/vTZfdNwwy4WwYogLh29DQ== + dependencies: + fb-watchman "^2.0.0" + graceful-fs "^4.1.11" + jest-docblock "^22.4.3" + jest-serializer "^22.4.3" + jest-worker "^22.4.3" + micromatch "^2.3.11" + sane "^2.0.0" + +jest-jasmine2@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-22.4.4.tgz#c55f92c961a141f693f869f5f081a79a10d24e23" + integrity sha512-nK3vdUl50MuH7vj/8at7EQVjPGWCi3d5+6aCi7Gxy/XMWdOdbH1qtO/LjKbqD8+8dUAEH+BVVh7HkjpCWC1CSw== + dependencies: + chalk "^2.0.1" + co "^4.6.0" + expect "^22.4.0" + graceful-fs "^4.1.11" + is-generator-fn "^1.0.0" + jest-diff "^22.4.0" + jest-matcher-utils "^22.4.0" + jest-message-util "^22.4.0" + jest-snapshot "^22.4.0" + jest-util "^22.4.1" + source-map-support "^0.5.0" + +jest-leak-detector@^22.4.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-22.4.3.tgz#2b7b263103afae8c52b6b91241a2de40117e5b35" + integrity sha512-NZpR/Ls7+ndO57LuXROdgCGz2RmUdC541tTImL9bdUtU3WadgFGm0yV+Ok4Fuia/1rLAn5KaJ+i76L6e3zGJYQ== + dependencies: + pretty-format "^22.4.3" + +jest-matcher-utils@^22.4.0, jest-matcher-utils@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz#4632fe428ebc73ebc194d3c7b65d37b161f710ff" + integrity sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA== + dependencies: + chalk "^2.0.1" + jest-get-type "^22.4.3" + pretty-format "^22.4.3" + +jest-message-util@^22.4.0, jest-message-util@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-22.4.3.tgz#cf3d38aafe4befddbfc455e57d65d5239e399eb7" + integrity sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA== + dependencies: + "@babel/code-frame" "^7.0.0-beta.35" + chalk "^2.0.1" + micromatch "^2.3.11" + slash "^1.0.0" + stack-utils "^1.0.1" + +jest-mock@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-22.4.3.tgz#f63ba2f07a1511772cdc7979733397df770aabc7" + integrity sha512-+4R6mH5M1G4NK16CKg9N1DtCaFmuxhcIqF4lQK/Q1CIotqMs/XBemfpDPeVZBFow6iyUNu6EBT9ugdNOTT5o5Q== + +jest-regex-util@^22.1.0, jest-regex-util@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-22.4.3.tgz#a826eb191cdf22502198c5401a1fc04de9cef5af" + integrity sha512-LFg1gWr3QinIjb8j833bq7jtQopiwdAs67OGfkPrvy7uNUbVMfTXXcOKXJaeY5GgjobELkKvKENqq1xrUectWg== + +jest-resolve-dependencies@^22.1.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-22.4.3.tgz#e2256a5a846732dc3969cb72f3c9ad7725a8195e" + integrity sha512-06czCMVToSN8F2U4EvgSB1Bv/56gc7MpCftZ9z9fBgUQM7dzHGCMBsyfVA6dZTx8v0FDcnALf7hupeQxaBCvpA== + dependencies: + jest-regex-util "^22.4.3" + +jest-resolve@^22.4.2: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-22.4.3.tgz#0ce9d438c8438229aa9b916968ec6b05c1abb4ea" + integrity sha512-u3BkD/MQBmwrOJDzDIaxpyqTxYH+XqAXzVJP51gt29H8jpj3QgKof5GGO2uPGKGeA1yTMlpbMs1gIQ6U4vcRhw== + dependencies: + browser-resolve "^1.11.2" + chalk "^2.0.1" + +jest-runner@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-22.4.4.tgz#dfca7b7553e0fa617e7b1291aeb7ce83e540a907" + integrity sha512-5S/OpB51igQW9xnkM5Tgd/7ZjiAuIoiJAVtvVTBcEBiXBIFzWM3BAMPBM19FX68gRV0KWyFuGKj0EY3M3aceeQ== + dependencies: + exit "^0.1.2" + jest-config "^22.4.4" + jest-docblock "^22.4.0" + jest-haste-map "^22.4.2" + jest-jasmine2 "^22.4.4" + jest-leak-detector "^22.4.0" + jest-message-util "^22.4.0" + jest-runtime "^22.4.4" + jest-util "^22.4.1" + jest-worker "^22.2.2" + throat "^4.0.0" + +jest-runtime@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-22.4.4.tgz#9ba7792fc75582a5be0f79af6f8fe8adea314048" + integrity sha512-WRTj9m///npte1YjuphCYX7GRY/c2YvJImU9t7qOwFcqHr4YMzmX6evP/3Sehz5DKW2Vi8ONYPCFWe36JVXxfw== + dependencies: + babel-core "^6.0.0" + babel-jest "^22.4.4" + babel-plugin-istanbul "^4.1.5" + chalk "^2.0.1" + convert-source-map "^1.4.0" + exit "^0.1.2" + graceful-fs "^4.1.11" + jest-config "^22.4.4" + jest-haste-map "^22.4.2" + jest-regex-util "^22.1.0" + jest-resolve "^22.4.2" + jest-util "^22.4.1" + jest-validate "^22.4.4" + json-stable-stringify "^1.0.1" + micromatch "^2.3.11" + realpath-native "^1.0.0" + slash "^1.0.0" + strip-bom "3.0.0" + write-file-atomic "^2.1.0" + yargs "^10.0.3" + +jest-serializer@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-22.4.3.tgz#a679b81a7f111e4766235f4f0c46d230ee0f7436" + integrity sha512-uPaUAppx4VUfJ0QDerpNdF43F68eqKWCzzhUlKNDsUPhjOon7ZehR4C809GCqh765FoMRtTVUVnGvIoskkYHiw== + +jest-snapshot@^22.4.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-22.4.3.tgz#b5c9b42846ffb9faccb76b841315ba67887362d2" + integrity sha512-JXA0gVs5YL0HtLDCGa9YxcmmV2LZbwJ+0MfyXBBc5qpgkEYITQFJP7XNhcHFbUvRiniRpRbGVfJrOoYhhGE0RQ== + dependencies: + chalk "^2.0.1" + jest-diff "^22.4.3" + jest-matcher-utils "^22.4.3" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + pretty-format "^22.4.3" + +jest-util@^22.4.1, jest-util@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-22.4.3.tgz#c70fec8eec487c37b10b0809dc064a7ecf6aafac" + integrity sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ== + dependencies: + callsites "^2.0.0" + chalk "^2.0.1" + graceful-fs "^4.1.11" + is-ci "^1.0.10" + jest-message-util "^22.4.3" + mkdirp "^0.5.1" + source-map "^0.6.0" + +jest-validate@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-22.4.4.tgz#1dd0b616ef46c995de61810d85f57119dbbcec4d" + integrity sha512-dmlf4CIZRGvkaVg3fa0uetepcua44DHtktHm6rcoNVtYlpwe6fEJRkMFsaUVcFHLzbuBJ2cPw9Gl9TKfnzMVwg== + dependencies: + chalk "^2.0.1" + jest-config "^22.4.4" + jest-get-type "^22.1.0" + leven "^2.1.0" + pretty-format "^22.4.0" + +jest-worker@^22.2.2, jest-worker@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-22.4.3.tgz#5c421417cba1c0abf64bf56bd5fb7968d79dd40b" + integrity sha512-B1ucW4fI8qVAuZmicFxI1R3kr2fNeYJyvIQ1rKcuLYnenFV5K5aMbxFj6J0i00Ju83S8jP2d7Dz14+AvbIHRYQ== + dependencies: + merge-stream "^1.0.1" + +jest@^22.4.4: + version "22.4.4" + resolved "https://registry.yarnpkg.com/jest/-/jest-22.4.4.tgz#ffb36c9654b339a13e10b3d4b338eb3e9d49f6eb" + integrity sha512-eBhhW8OS/UuX3HxgzNBSVEVhSuRDh39Z1kdYkQVWna+scpgsrD7vSeBI7tmEvsguPDMnfJodW28YBnhv/BzSew== + dependencies: + import-local "^1.0.0" + jest-cli "^22.4.4" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^3.7.0, js-yaml@^3.8.4: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@^11.5.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" + integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw== + dependencies: + abab "^2.0.0" + acorn "^5.5.3" + acorn-globals "^4.1.0" + array-equal "^1.0.0" + cssom ">= 0.3.2 < 0.4.0" + cssstyle "^1.0.0" + data-urls "^1.0.0" + domexception "^1.0.1" + escodegen "^1.9.1" + html-encoding-sniffer "^1.0.2" + left-pad "^1.3.0" + nwsapi "^2.0.7" + parse5 "4.0.0" + pn "^1.1.0" + request "^2.87.0" + request-promise-native "^1.0.5" + sax "^1.2.4" + symbol-tree "^3.2.2" + tough-cookie "^2.3.4" + w3c-hr-time "^1.0.1" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.3" + whatwg-mimetype "^2.1.0" + whatwg-url "^6.4.1" + ws "^5.2.0" + xml-name-validator "^3.0.0" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +jsinspect@^0.12.6: + version "0.12.7" + resolved "https://registry.yarnpkg.com/jsinspect/-/jsinspect-0.12.7.tgz#a3f8eea47ca8931b94d62062089ebda099866854" + integrity sha512-9pLr5r5moX3XhACEg/nhIlprBuqRDT+loYigZo7hidmfOj0EV2l6ZMk6gmaNMiX6o1YCMod1lWSH3JoX80QHLA== + dependencies: + babylon "6.16.1" + chalk "^2.1.0" + commander "^2.11.0" + filepaths "0.3.0" + stable "^0.1.6" + strip-indent "^1.0.1" + strip-json-comments "1.0.2" + +json-loader@^0.5.4: + version "0.5.7" + resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" + integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.0, json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +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" + integrity sha1-6AGxs5mF4g//yHtA43SAgOLcrH8= + dependencies: + array-includes "^3.0.3" + +just-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" + integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= + +kew@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" + integrity sha1-edk9LTM2PW/dKXCzNdkUGtWR15s= + +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.0.4, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0, kind-of@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +last-run@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" + integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= + dependencies: + default-resolution "^2.0.0" + es6-weak-map "^2.0.1" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= + +lazystream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + dependencies: + readable-stream "^2.0.5" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +lead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + dependencies: + flush-write-stream "^1.0.2" + +left-pad@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" + integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== + +leven@^2.0.0, leven@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +liftoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" + integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew= + dependencies: + extend "^3.0.0" + findup-sync "^2.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +loader-runner@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" + integrity sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI= + +loader-utils@^0.2.16: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +loader-utils@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" + integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + +loader-utils@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash._baseclone@~4.5.0: + version "4.5.7" + resolved "https://registry.yarnpkg.com/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz#ce42ade08384ef5d62fa77c30f61a46e686f8434" + integrity sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ= + +lodash.clone@~4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.3.2.tgz#e56b176b6823a7dde38f7f2bf58de7d5971200e9" + integrity sha1-5WsXa2gjp93jj38r9Y3n1ZcSAOk= + dependencies: + lodash._baseclone "~4.5.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + +lodash.map@^4.5.1: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= + +lodash@4.17.5: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + integrity sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw== + +lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.3.0: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + +loose-envify@^1.0.0, loose-envify@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loud-rejection@^1.2.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lru-cache@^4.0.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-queue@0.1: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= + dependencies: + es5-ext "~0.10.2" + +make-iterator@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== + dependencies: + kind-of "^6.0.2" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + +map-cache@^0.2.0, map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +matchdep@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" + integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= + dependencies: + findup-sync "^2.0.0" + micromatch "^3.0.4" + resolve "^1.4.0" + stack-trace "0.0.10" + +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= + +md5.js@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" + integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0= + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + +memoizee@0.4.X: + version "0.4.12" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.12.tgz#780e99a219c50c549be6d0fc61765080975c58fb" + integrity sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg== + dependencies: + d "1" + es5-ext "^0.10.30" + es6-weak-map "^2.0.2" + event-emitter "^0.3.5" + is-promise "^2.1" + lru-queue "0.1" + next-tick "1" + timers-ext "^0.1.2" + +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-stream@^1.0.0, merge-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= + dependencies: + readable-stream "^2.0.1" + +merge@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" + integrity sha1-dTHjnUlJwoGma4xabgJl6LBYlNo= + +micromatch@^2.3.11, micromatch@^2.3.7: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.0.4, micromatch@^3.1.4, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + integrity sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg== + +mime-types@^2.1.12, mime-types@~2.1.17: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + integrity sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw== + dependencies: + mime-db "~1.35.0" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + integrity sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA== + dependencies: + minipass "^2.2.1" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mock-stdin@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/mock-stdin/-/mock-stdin-0.3.1.tgz#c657d9642d90786435c64ca5e99bbd4d09bd7dd3" + integrity sha1-xlfZZC2QeGQ1xkyl6Zu9TQm9fdM= + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +mute-stdout@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.0.tgz#5b32ea07eb43c9ded6130434cf926f46b2a7fd4d" + integrity sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0= + +mute-stream@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" + integrity sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s= + +mute-stream@0.0.7, mute-stream@~0.0.4: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +mz@^2.5.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +needle@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + integrity sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +neo-async@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee" + integrity sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA== + +next-tick@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +nice-try@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" + integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== + +node-emoji@^1.6.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.8.1.tgz#6eec6bfb07421e2148c75c6bba72421f8530a826" + integrity sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg== + dependencies: + lodash.toarray "^4.4.0" + +node-fetch@1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" + integrity sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ= + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-libs-browser@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" + integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.0" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + +node-notifier@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" + integrity sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg== + dependencies: + growly "^1.3.0" + semver "^5.4.1" + shellwords "^0.1.1" + which "^1.3.0" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1, normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-url@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + +now-and-later@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" + integrity sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4= + dependencies: + once "^1.3.2" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + integrity sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow== + +npm-logical-tree@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" + integrity sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg== + +npm-packlist@^1.1.6: + version "1.1.11" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + integrity sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +nwsapi@^2.0.7: + version "2.0.8" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.8.tgz#e3603579b7e162b3dbedae4fb24e46f771d8fa24" + integrity sha512-7RZ+qbFGiVc6v14Y8DSZjPN1wZPOaMbiiP4tzf5eNuyOITAeOIA3cMhjuKUypVIqBgCSg1KaSyAv8Ocq/0ZJ1A== + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= + +object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.11, object-keys@^1.0.8: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== + +object-path@^0.11.2: + version "0.11.4" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949" + integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.0.4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.defaults@^1.0.0, object.defaults@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= + dependencies: + array-each "^1.0.1" + array-slice "^1.0.0" + for-own "^1.0.0" + isobject "^3.0.0" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.map@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +object.pick@^1.2.0, object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.reduce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" + integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + +once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +opencollective@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" + integrity sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE= + dependencies: + babel-polyfill "6.23.0" + chalk "1.1.3" + inquirer "3.0.6" + minimist "1.2.0" + node-fetch "1.6.3" + opn "4.0.2" + +opn@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" + integrity sha1-erwi5kTf9jsKltWrfyeQwPAavJU= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.1, optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +ordered-read-streams@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + dependencies: + readable-stream "^2.0.1" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0, os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-shim@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" + integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +pad-right@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/pad-right/-/pad-right-0.2.2.tgz#6fbc924045d244f2a2a244503060d3bfc6009774" + integrity sha1-b7ySQEXSRPKiokRQMGDTv8YAl3Q= + dependencies: + repeat-string "^1.5.2" + +pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= + +pako@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== + +parse-asn1@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + +parse-filepath@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +parse5@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" + integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@2.1.0, path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-extra@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/path-extra/-/path-extra-1.0.3.tgz#7c112189a6e50d595790e7ad2037e44e410c1166" + integrity sha1-fBEhiablDVlXkOetIDfkTkEMEWY= + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + integrity sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME= + +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pbkdf2@^3.0.3: + version "3.0.16" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" + integrity sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +peek-stream@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67" + integrity sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA== + dependencies: + buffer-from "^1.0.0" + duplexify "^3.5.0" + through2 "^2.0.3" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= + dependencies: + find-up "^1.0.0" + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +plugin-error@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" + integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== + dependencies: + ansi-colors "^1.0.1" + arr-diff "^4.0.0" + arr-union "^3.1.0" + extend-shallow "^3.0.2" + +pluralize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" + integrity sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I= + +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + +prettier@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.5.2.tgz#7ea0751da27b93bfb6cecfcec509994f52d83bb3" + integrity sha512-f55mvineQ5yc36cLX4n4RWP6JH6MLcfi5f9MVsjpfBs4MVSG2GYT4v6cukzmvkIOvmNOdCZfDSMY3hQcMcDQbQ== + +pretty-format@^22.4.0, pretty-format@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f" + integrity sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ== + dependencies: + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" + +pretty-hrtime@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= + +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= + +prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== + dependencies: + loose-envify "^1.3.1" + object-assign "^4.1.1" + +proper-lockfile@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-2.0.1.tgz#159fb06193d32003f4b3691dd2ec1a634aa80d1d" + integrity sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0= + dependencies: + graceful-fs "^4.1.2" + retry "^0.10.0" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.24: + version "1.1.28" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.28.tgz#4fb6ceb08a1e2214d4fd4de0ca22dae13740bc7b" + integrity sha512-+AqO1Ae+N/4r7Rvchrdm432afjT9hqJRyBN3DQv9At0tPz4hIFSGKbq64fN9dVoCow4oggIIax5/iONx0r9hZw== + +public-encrypt@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" + integrity sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + +puka@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/puka/-/puka-1.0.0.tgz#1dd92f9f81f6c53390a17529b7aebaa96604ad97" + integrity sha512-JOY9vNkLjpwi/CtwsZfGcZZiHb+HfOJjjdz93v6150EPNQgb5JDeImlI48r/kZ5i9bNCSjXpU+eyYIxoujhNLw== + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3, pumpify@^1.3.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +randomatic@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" + integrity sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= + dependencies: + mute-stream "~0.0.4" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + integrity sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg= + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +realpath-native@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.1.tgz#07f40a0cce8f8261e2e8b7ebebf5c95965d7b633" + integrity sha512-W14EcXuqUvKP8dkWkD7B95iMy77lpMnlFXbbk409bQtNCbeu0kvRE5reo+yIZ3JXxg6frbGsz2DLQ39lrCB40g== + dependencies: + util.promisify "^1.0.0" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +regenerate@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.10.0: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +remove-bom-buffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== + dependencies: + is-buffer "^1.1.5" + is-utf8 "^0.2.1" + +remove-bom-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + dependencies: + remove-bom-buffer "^3.0.0" + safe-buffer "^5.1.0" + through2 "^2.0.3" + +remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= + +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +replace-homedir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" + integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= + dependencies: + homedir-polyfill "^1.0.1" + is-absolute "^1.0.0" + remove-trailing-separator "^1.1.0" + +request-capture-har@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/request-capture-har/-/request-capture-har-1.2.2.tgz#cd692cfb2cc744fd84a3358aac6ee51528cf720d" + integrity sha1-zWks+yzHRP2EozWKrG7lFSjPcg0= + +request-promise-core@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" + integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= + dependencies: + lodash "^4.13.1" + +request-promise-native@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" + integrity sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU= + dependencies: + request-promise-core "1.1.1" + stealthy-require "^1.1.0" + tough-cookie ">=2.3.3" + +request@^2.87.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-resolve@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/require-resolve/-/require-resolve-0.0.2.tgz#bab410ab1aee2f3f55b79317451dd3428764e6f3" + integrity sha1-urQQqxruLz9Vt5MXRR3TQodk5vM= + dependencies: + x-path "^0.0.2" + +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" + integrity sha1-shklmlYC+sXFxJatiUpujMQwJh4= + dependencies: + expand-tilde "^1.2.2" + global-modules "^0.2.3" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-options@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + dependencies: + value-or-function "^3.0.0" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.4.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== + dependencies: + path-parse "^1.0.5" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= + dependencies: + align-text "^0.1.1" + +right-pad@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" + integrity sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA= + +rimraf@^2.2.8, rimraf@^2.5.0, rimraf@^2.5.4, rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== + dependencies: + glob "^7.0.5" + +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + integrity sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI= + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rsvp@^3.3.3: + version "3.6.2" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" + integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== + +rsvp@~3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a" + integrity sha1-B8tKXfJa3Z6Cbrxn3Mn9idsn2Eo= + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= + +rx@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" + integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= + +rxjs@^6.1.0: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" + integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sane@^2.0.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" + integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o= + dependencies: + anymatch "^2.0.0" + capture-exit "^1.2.0" + exec-sh "^0.2.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + watch "~0.18.0" + optionalDependencies: + fsevents "^1.2.3" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +schema-utils@^0.4.5: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +semver-greatest-satisfied-range@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" + integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= + dependencies: + sver-compat "^1.5.0" + +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shelljs@0.7.6: + version "0.7.6" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad" + integrity sha1-N5zM+1a5HIYB5HkzVutTgpJN6a0= + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== + dependencies: + is-fullwidth-code-point "^2.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= + dependencies: + is-plain-obj "^1.0.0" + +source-list-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" + integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A== + +source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" + integrity sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.1.38: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= + dependencies: + amdefine ">=0.0.4" + +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + integrity sha1-66T12pwNyZneaAMti092FzZSA2s= + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sparkles@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== + +spawn-sync@^1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" + integrity sha1-sAeZVX63+wyDdsKdROih6mfldHY= + dependencies: + concat-stream "^1.4.7" + os-shim "^0.1.2" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + integrity sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + integrity sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + integrity sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.14.2, sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + integrity sha1-xvxhZIo9nE52T9P8306hBeSSupg= + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +ssri@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" + integrity sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ== + dependencies: + safe-buffer "^5.1.1" + +stable@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stack-trace@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + +stack-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" + integrity sha1-1PM6tU6OOHeLDKXP07OvsS22hiA= + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +stealthy-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-exhaust@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" + integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-length@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" + integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= + dependencies: + astral-regex "^1.0.0" + strip-ansi "^4.0.0" + +string-replace-loader@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-2.1.1.tgz#b72e7b57b6ef04efe615aff0ad989b5c14ca63d1" + integrity sha512-0Nvw1LDclF45AFNuYPcD2Jvkv0mwb/dQSnJZMvhqGrT+zzmrpG3OJFD600qfQfNUd5aqfp7fCm2mQMfF7zLbyQ== + dependencies: + loader-utils "^1.1.0" + schema-utils "^0.4.5" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-bom-string@1.X: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + +strip-bom@3.0.0, strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.2.tgz#5a48ab96023dbac1b7b8d0ffabf6f63f1677be9f" + integrity sha1-WkirlgI9usG3uND/q/b2PxZ3vp8= + +strip-json-comments@2.0.1, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.1.0, supports-color@^3.1.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + +sver-compat@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" + integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= + dependencies: + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +symbol-tree@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" + integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= + +table@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" + integrity sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg== + dependencies: + ajv "^6.0.1" + ajv-keywords "^3.0.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + +tapable@^0.2.7, tapable@~0.2.5: + version "0.2.8" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" + integrity sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI= + +tar-fs@^1.16.0: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2, tar-stream@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" + integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.1.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.0" + xtend "^4.0.0" + +tar@^4: + version "4.4.6" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +temp@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" + integrity sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k= + dependencies: + os-tmpdir "^1.0.0" + rimraf "~2.2.6" + +ternary-stream@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-2.0.1.tgz#064e489b4b5bf60ba6a6b7bc7f2f5c274ecf8269" + integrity sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk= + dependencies: + duplexify "^3.5.0" + fork-stream "^0.0.4" + merge-stream "^1.0.0" + through2 "^2.0.1" + +test-exclude@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" + integrity sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ== + dependencies: + arrify "^1.0.1" + micromatch "^3.1.8" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= + dependencies: + any-promise "^1.0.0" + +throat@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= + +through2-filter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" + integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= + dependencies: + through2 "~2.0.0" + xtend "~4.0.0" + +through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= + +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" + integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + dependencies: + setimmediate "^1.0.4" + +timers-ext@^0.1.2: + version "0.1.5" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.5.tgz#77147dd4e76b660c2abb8785db96574cbbd12922" + integrity sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg== + dependencies: + es5-ext "~0.10.14" + next-tick "1" + +tmp@^0.0.29: + version "0.0.29" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" + integrity sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA= + dependencies: + os-tmpdir "~1.0.1" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + +to-absolute-glob@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-buffer@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +to-through@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + dependencies: + through2 "^2.0.3" + +tough-cookie@>=2.3.3, tough-cookie@^2.3.4: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== + dependencies: + punycode "^1.4.1" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uglify-js@^2.6, uglify-js@^2.8.27: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +undertaker-registry@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" + integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= + +undertaker@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.0.tgz#339da4646252d082dc378e708067299750e11b49" + integrity sha1-M52kZGJS0ILcN45wgGcpl1DhG0k= + dependencies: + arr-flatten "^1.0.1" + arr-map "^2.0.0" + bach "^1.0.0" + collection-map "^1.0.0" + es6-weak-map "^2.0.1" + last-run "^1.1.0" + object.defaults "^1.0.0" + object.reduce "^1.0.0" + undertaker-registry "^1.0.0" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unique-stream@^2.0.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" + integrity sha1-WqADz76Uxf+GbE59ZouxxNuts2k= + dependencies: + json-stable-stringify "^1.0.0" + through2-filter "^2.0.0" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== + +uri-js@^4.2.1, uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +uuid@^3.0.1, uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +v8-compile-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a" + integrity sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg== + +v8flags@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.1.tgz#42259a1461c08397e37fe1d4f1cfb59cad85a053" + integrity sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ== + dependencies: + homedir-polyfill "^1.0.1" + +validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +value-or-function@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" + integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl-fs@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + +vinyl-sourcemap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + dependencies: + append-buffer "^1.0.2" + convert-source-map "^1.5.0" + graceful-fs "^4.1.6" + normalize-path "^2.1.1" + now-and-later "^2.0.0" + remove-bom-buffer "^3.0.0" + vinyl "^2.0.0" + +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= + dependencies: + source-map "^0.5.1" + +vinyl@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + +vm-browserify@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= + dependencies: + indexof "0.0.1" + +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + dependencies: + browser-process-hrtime "^0.1.2" + +walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + +watch@~0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" + integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= + dependencies: + exec-sh "^0.2.0" + minimist "^1.2.0" + +watchpack@^1.3.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +webpack-sources@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54" + integrity sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^2.1.0-beta.25: + version "2.7.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.7.0.tgz#b2a1226804373ffd3d03ea9c6bd525067034f6b1" + integrity sha512-MjAA0ZqO1ba7ZQJRnoCdbM56mmFpipOPUv/vQpwwfSI42p5PVDdoiuK2AL2FwFUVgT859Jr43bFZXRg/LNsqvg== + dependencies: + acorn "^5.0.0" + acorn-dynamic-import "^2.0.0" + ajv "^4.7.0" + ajv-keywords "^1.1.1" + async "^2.1.2" + enhanced-resolve "^3.3.0" + interpret "^1.0.0" + json-loader "^0.5.4" + json5 "^0.5.1" + loader-runner "^2.3.0" + loader-utils "^0.2.16" + memory-fs "~0.4.1" + mkdirp "~0.5.0" + node-libs-browser "^2.0.0" + source-map "^0.5.3" + supports-color "^3.1.0" + tapable "~0.2.5" + uglify-js "^2.8.27" + watchpack "^1.3.1" + webpack-sources "^1.0.1" + yargs "^6.0.0" + +whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3" + integrity sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw== + dependencies: + iconv-lite "0.4.19" + +whatwg-mimetype@^2.0.0, whatwg-mimetype@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" + integrity sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew== + +whatwg-url@^6.4.0, whatwg-url@^6.4.1: + version "6.5.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" + integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= + +word-wrap@^1.0.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + +ws@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== + dependencies: + async-limiter "~1.0.0" + +x-path@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/x-path/-/x-path-0.0.2.tgz#294d076bb97a7706cc070bbb2a6fd8c54df67b12" + integrity sha1-KU0Ha7l6dwbMBwu7Km/YxU32exI= + dependencies: + path-extra "^1.0.2" + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= + +yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= + dependencies: + camelcase "^3.0.0" + +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= + dependencies: + camelcase "^3.0.0" + +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== + dependencies: + camelcase "^4.1.0" + +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" + +yargs@^6.0.0, yargs@^6.3.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + +yargs@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha1-5a2ryKz0CPY4X8dklWhMiOavaJo= \ No newline at end of file diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/.gitignore b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/.gitignore new file mode 100644 index 0000000000..2747790c35 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/.gitignore @@ -0,0 +1 @@ +bun.* \ No newline at end of file diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/mkdirp/package.json b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/mkdirp/package.json new file mode 100644 index 0000000000..cfd04ed65f --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/mkdirp/package.json @@ -0,0 +1,44 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "1.0.2", + "main": "index.js", + "keywords": [ + "mkdir", + "directory", + "make dir", + "make", + "dir", + "recursive", + "native" + ], + "repository": { + "type": "git", + "url": "https://github.com/isaacs/node-mkdirp.git" + }, + "scripts": { + "test": "tap", + "snap": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --follow-tags" + }, + "tap": { + "check-coverage": true, + "coverage-map": "map.js" + }, + "devDependencies": { + "require-inject": "^1.4.4", + "tap": "^14.10.6" + }, + "bin": "bin/cmd.js", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "files": [ + "bin", + "lib", + "index.js" + ] +} diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/package.json b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/package.json new file mode 100644 index 0000000000..f7c1f0b047 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "mkdirp": "file:mkdirp" + } +} diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/yarn.lock b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/yarn.lock new file mode 100644 index 0000000000..3d80e85125 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-file-dep/yarn.lock @@ -0,0 +1,6 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"mkdirp@file:mkdirp": + version "1.0.2" diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/.gitignore b/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/.gitignore new file mode 100644 index 0000000000..2747790c35 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/.gitignore @@ -0,0 +1 @@ +bun.* \ No newline at end of file diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/package.json b/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/package.json new file mode 100644 index 0000000000..abcc24b1b8 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "mkdirp": "^1.0.2" + } +} diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/yarn.lock b/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/yarn.lock new file mode 100644 index 0000000000..539babc61f --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp-no-resolved/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +mkdirp@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp/.gitignore b/test/cli/install/migration/yarn/yarn-lock-mkdirp/.gitignore new file mode 100644 index 0000000000..2747790c35 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp/.gitignore @@ -0,0 +1 @@ +bun.* \ No newline at end of file diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp/package.json b/test/cli/install/migration/yarn/yarn-lock-mkdirp/package.json new file mode 100644 index 0000000000..abcc24b1b8 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "mkdirp": "^1.0.2" + } +} diff --git a/test/cli/install/migration/yarn/yarn-lock-mkdirp/yarn.lock b/test/cli/install/migration/yarn/yarn-lock-mkdirp/yarn.lock new file mode 100644 index 0000000000..539babc61f --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-lock-mkdirp/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +mkdirp@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== diff --git a/test/cli/install/migration/yarn/yarn-stuff/.gitignore b/test/cli/install/migration/yarn/yarn-stuff/.gitignore new file mode 100644 index 0000000000..2747790c35 --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-stuff/.gitignore @@ -0,0 +1 @@ +bun.* \ No newline at end of file diff --git a/test/cli/install/migration/yarn/yarn-stuff/abbrev-1.1.1.tgz b/test/cli/install/migration/yarn/yarn-stuff/abbrev-1.1.1.tgz new file mode 100644 index 0000000000..4d9504504f Binary files /dev/null and b/test/cli/install/migration/yarn/yarn-stuff/abbrev-1.1.1.tgz differ diff --git a/test/cli/install/migration/yarn/yarn-stuff/abbrev-link-target/package.json b/test/cli/install/migration/yarn/yarn-stuff/abbrev-link-target/package.json new file mode 100644 index 0000000000..4772bd3c5d --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-stuff/abbrev-link-target/package.json @@ -0,0 +1 @@ +{"name":"abbrev","version":"1.1.1"} diff --git a/test/cli/install/migration/yarn/yarn-stuff/abbrev-link-target/yarn.lock b/test/cli/install/migration/yarn/yarn-stuff/abbrev-link-target/yarn.lock new file mode 100644 index 0000000000..fb57ccd13a --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-stuff/abbrev-link-target/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + diff --git a/test/cli/install/migration/yarn/yarn-stuff/package.json b/test/cli/install/migration/yarn/yarn-stuff/package.json new file mode 100644 index 0000000000..9e841e104f --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-stuff/package.json @@ -0,0 +1,15 @@ +{ + "name": "a", + "version": "1.2.3", + "dependencies": { + "abbrev": "^1.1.1", + "full-git-url": "git+https://github.com/isaacs/abbrev-js.git", + "ghshort": "github:isaacs/abbrev-js", + "old": "npm:abbrev@1.0.x", + "pinned": "npm:abbrev@1.1.1", + "reg": "npm:abbrev@^1.1.1", + "remote": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "symlink": "file:./abbrev-link-target", + "tarball": "file:abbrev-1.1.1.tgz" + } +} diff --git a/test/cli/install/migration/yarn/yarn-stuff/yarn.lock b/test/cli/install/migration/yarn/yarn-stuff/yarn.lock new file mode 100644 index 0000000000..07af34067d --- /dev/null +++ b/test/cli/install/migration/yarn/yarn-stuff/yarn.lock @@ -0,0 +1,42 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +"full-git-url@git+https://github.com/isaacs/abbrev-js.git": + version "3.0.1" + resolved "git+https://github.com/isaacs/abbrev-js.git#3f9802e56ff878761a338e43ecacbfed39d2181d" + +"ghshort@github:isaacs/abbrev-js": + version "3.0.1" + resolved "https://codeload.github.com/isaacs/abbrev-js/tar.gz/3f9802e56ff878761a338e43ecacbfed39d2181d" + +"old@npm:abbrev@1.0.x": + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== + +"pinned@npm:abbrev@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +"reg@npm:abbrev@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +"remote@https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz": + version "1.1.1" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +"symlink@file:./abbrev-link-target": + version "1.1.1" + +"tarball@file:abbrev-1.1.1.tgz": + version "1.1.1" + resolved "file:abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" diff --git a/test/cli/install/registry/packages/lifecycle-preinstall/lifecycle-preinstall-1.0.0.tgz b/test/cli/install/registry/packages/lifecycle-preinstall/lifecycle-preinstall-1.0.0.tgz new file mode 100644 index 0000000000..5e87227d8b Binary files /dev/null and b/test/cli/install/registry/packages/lifecycle-preinstall/lifecycle-preinstall-1.0.0.tgz differ diff --git a/test/cli/install/registry/packages/lifecycle-preinstall/package.json b/test/cli/install/registry/packages/lifecycle-preinstall/package.json new file mode 100644 index 0000000000..a12f8f1d9f --- /dev/null +++ b/test/cli/install/registry/packages/lifecycle-preinstall/package.json @@ -0,0 +1,44 @@ +{ + "name": "lifecycle-preinstall", + "versions": { + "1.0.0": { + "name": "lifecycle-preinstall", + "version": "1.0.0", + "scripts": { + "preinstall": "bun preinstall.js" + }, + "_id": "lifecycle-preinstall@1.0.0", + "_integrity": "sha512-62WGgQIgbtfaxP+eiW2XThZ4m7XOElX/3Wx7afjM5A60XYbPmRXw9TasVm0DXM+wYjf5HLwc0lsvlvJzetyD/A==", + "_nodeVersion": "24.3.0", + "_npmVersion": "10.8.3", + "integrity": "sha512-62WGgQIgbtfaxP+eiW2XThZ4m7XOElX/3Wx7afjM5A60XYbPmRXw9TasVm0DXM+wYjf5HLwc0lsvlvJzetyD/A==", + "shasum": "bc494b4c920f8a4b09912f0ab6bb22a32d682857", + "dist": { + "integrity": "sha512-62WGgQIgbtfaxP+eiW2XThZ4m7XOElX/3Wx7afjM5A60XYbPmRXw9TasVm0DXM+wYjf5HLwc0lsvlvJzetyD/A==", + "shasum": "bc494b4c920f8a4b09912f0ab6bb22a32d682857", + "tarball": "http://http://localhost:4873/lifecycle-preinstall/-/lifecycle-preinstall-1.0.0.tgz" + }, + "contributors": [] + } + }, + "time": { + "modified": "2025-07-28T07:46:41.246Z", + "created": "2025-07-28T07:46:41.246Z", + "1.0.0": "2025-07-28T07:46:41.246Z" + }, + "users": {}, + "dist-tags": { + "latest": "1.0.0" + }, + "_uplinks": {}, + "_distfiles": {}, + "_attachments": { + "lifecycle-preinstall-1.0.0.tgz": { + "shasum": "bc494b4c920f8a4b09912f0ab6bb22a32d682857", + "version": "1.0.0" + } + }, + "_rev": "", + "_id": "lifecycle-preinstall", + "readme": "" +} \ No newline at end of file diff --git a/test/cli/test/test-filter-lifecycle-snapshot.test.ts b/test/cli/test/test-filter-lifecycle-snapshot.test.ts new file mode 100644 index 0000000000..d3695f5636 --- /dev/null +++ b/test/cli/test/test-filter-lifecycle-snapshot.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe, normalizeBunSnapshot } from "harness"; +import { join } from "node:path"; + +test("snapshot", () => { + const { stdout, stderr, exitCode } = Bun.spawnSync({ + cmd: [bunExe(), "test", join(import.meta.dirname, "test-filter-lifecycle.js"), "-t", "should run test"], + stdout: "pipe", + stderr: "pipe", + stdin: "ignore", + env: bunEnv, + }); + + expect(normalizeBunSnapshot(stdout.toString() + stderr.toString())).toMatchInlineSnapshot(` + "bun test () + + + + + + + + + + + + + + + + test/cli/test/test-filter-lifecycle.js: + (pass) parent > should run > test + (pass) parent > should run > test 2 + + 2 pass + 4 filtered out + 0 fail + Ran 2 tests across 1 file." + `); + expect(exitCode).toBe(0); +}); diff --git a/test/cli/test/test-filter-lifecycle.js b/test/cli/test/test-filter-lifecycle.js new file mode 100644 index 0000000000..32b260d13c --- /dev/null +++ b/test/cli/test/test-filter-lifecycle.js @@ -0,0 +1,133 @@ +// This test is intended to be able to run in Vitest and Jest. +describe("top-level sibling", () => { + beforeAll(() => { + throw new Error("FAIL"); + }); + + afterAll(() => { + throw new Error("FAIL"); + }); + + beforeEach(() => { + throw new Error("FAIL"); + }); + + afterEach(() => { + throw new Error("FAIL"); + }); + + test("test", () => { + throw new Error("FAIL"); + }); +}); + +describe("parent", () => { + let ran = { + beforeAll: 0, + beforeEach: 0, + afterEach: 0, + afterAll: 0, + }; + + beforeEach(() => { + if (++ran.beforeEach > 2) { + throw new Error("FAIL"); + } + + console.log(""); + }); + + afterEach(() => { + if (++ran.afterEach > 2) { + throw new Error("FAIL"); + } + + console.log(""); + }); + + beforeAll(() => { + if (++ran.beforeAll > 1) { + throw new Error("FAIL"); + } + + console.log(""); + }); + + afterAll(() => { + if (++ran.afterAll > 1) { + throw new Error("FAIL"); + } + + console.log(""); + }); + + describe("sibling describe", () => { + beforeEach(() => { + throw new Error("FAIL"); + }); + + afterEach(() => { + throw new Error("FAIL"); + }); + + test("test", () => { + throw new Error("FAIL"); + }); + }); + + describe("should run", () => { + let ran = { + beforeAll: 0, + beforeEach: 0, + afterEach: 0, + afterAll: 0, + }; + beforeAll(() => { + if (++ran.beforeAll > 1) { + throw new Error("FAIL"); + } + + console.log(""); + }); + + afterAll(() => { + if (++ran.afterAll > 1) { + throw new Error("FAIL"); + } + + console.log(""); + }); + + beforeEach(() => { + if (++ran.beforeEach > 2) { + throw new Error("FAIL 1"); + } + + console.log(""); + }); + + afterEach(() => { + if (++ran.afterEach > 2) { + throw new Error("FAIL 2"); + } + + console.log(""); + }); + + test("before sibling", () => { + throw new Error("FAIL"); + }); + + test("test", () => { + console.log(""); + }); + + test("test 2", () => { + console.log(""); + }); + + test("FAIL", () => { + throw new Error("FAIL"); + }); + }); +}); diff --git a/test/cli/update_interactive_formatting.test.ts b/test/cli/update_interactive_formatting.test.ts index 7b28c7318f..8e54570781 100644 --- a/test/cli/update_interactive_formatting.test.ts +++ b/test/cli/update_interactive_formatting.test.ts @@ -1,8 +1,21 @@ -import { describe, expect, it } from "bun:test"; -import { bunEnv, bunExe, tempDirWithFiles } from "harness"; +import { afterAll, beforeAll, describe, expect, it } from "bun:test"; +import { bunEnv, bunExe, tempDirWithFiles, VerdaccioRegistry } from "harness"; import { join } from "path"; -describe("bun update --interactive formatting", () => { +let registry: VerdaccioRegistry; +let registryUrl: string; + +beforeAll(async () => { + registry = new VerdaccioRegistry(); + registryUrl = registry.registryUrl(); + await registry.start(); +}); + +afterAll(() => { + registry.stop(); +}); + +describe("bun update --interactive", () => { it("should handle package names of unusual lengths", async () => { const dir = tempDirWithFiles("update-interactive-test", { "package.json": JSON.stringify({ @@ -207,6 +220,86 @@ describe("bun update --interactive formatting", () => { expect(stderr).not.toContain("overflow"); }); + it("should show workspace column with --filter", async () => { + const dir = tempDirWithFiles("update-interactive-workspace-col-test", { + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + }), + "packages/pkg1/package.json": JSON.stringify({ + name: "pkg1", + dependencies: { + "dep1": "1.0.0", + }, + }), + "packages/pkg2/package.json": JSON.stringify({ + name: "pkg2", + dependencies: { + "dep2": "1.0.0", + }, + }), + }); + + // Test with --filter should include workspace column + const result = await Bun.spawn({ + cmd: [bunExe(), "update", "--interactive", "--filter=*", "--dry-run"], + cwd: dir, + env: bunEnv, + stdin: "inherit", + stdout: "pipe", + stderr: "pipe", + }); + + const stderr = await new Response(result.stderr).text(); + + // Should not crash with workspace column + expect(stderr).not.toContain("panic"); + expect(stderr).not.toContain("segfault"); + }); + + it("should handle catalog dependencies in interactive update", async () => { + const dir = tempDirWithFiles("update-interactive-catalog-test", { + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + catalog: { + "shared-dep": "1.0.0", + }, + workspaces: ["packages/*"], + }), + "packages/pkg1/package.json": JSON.stringify({ + name: "pkg1", + dependencies: { + "shared-dep": "catalog:", + }, + }), + "packages/pkg2/package.json": JSON.stringify({ + name: "pkg2", + dependencies: { + "shared-dep": "catalog:", + }, + }), + }); + + // Test interactive update with catalog dependencies + const result = await Bun.spawn({ + cmd: [bunExe(), "update", "--interactive", "--filter=*", "--dry-run"], + cwd: dir, + env: bunEnv, + stdin: "inherit", + stdout: "pipe", + stderr: "pipe", + }); + + const stderr = await new Response(result.stderr).text(); + + // Should not crash with catalog dependencies + expect(stderr).not.toContain("panic"); + expect(stderr).not.toContain("segfault"); + expect(stderr).not.toContain("catalog: failed to resolve"); + }); + it("should handle mixed dependency types with various name lengths", async () => { const dir = tempDirWithFiles("update-interactive-mixed-test", { "package.json": JSON.stringify({ @@ -264,4 +357,1596 @@ describe("bun update --interactive formatting", () => { expect(stderr).not.toContain("underflow"); expect(stderr).not.toContain("overflow"); }); + + it("should update packages when 'a' (select all) is used", async () => { + const dir = tempDirWithFiles("update-interactive-select-all", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", // Old version + }, + }), + }); + + // First install to get lockfile + const install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Test interactive update with 'a' to select all + const update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then Enter to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const stdout = await new Response(update.stdout).text(); + const stderr = await new Response(update.stderr).text(); + const output = stdout + stderr; + + if (exitCode !== 0) { + console.error("Update failed with exit code:", exitCode); + console.error("Stdout:", stdout); + console.error("Stderr:", stderr); + } + + // Should complete successfully + expect(exitCode).toBe(0); + expect(stderr).not.toContain("panic"); + + // Check if package.json was updated + const packageJson = await Bun.file(join(dir, "package.json")).json(); + // no-deps should be updated from 1.0.0 to 2.0.0 + expect(packageJson.dependencies["no-deps"]).toBe("2.0.0"); + + // Check that the output shows the package was installed/updated + expect(output).toContain("Installing updates..."); + + // todo: Should show the installed package in the summary + // expect(output).toContain("installed no-deps@"); + + // Should save the lockfile + expect(output).toContain("Saved lockfile"); + }); + + it("should handle workspace updates with recursive flag", async () => { + const dir = tempDirWithFiles("update-interactive-workspace-recursive", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + private: true, + workspaces: ["packages/*"], + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", // Old version in workspace + }, + }), + }); + + // First install + const install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Test interactive update with recursive flag + const update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Select all packages + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const stderr = await new Response(update.stderr).text(); + + expect(exitCode).toBe(0); + expect(stderr).not.toContain("panic"); + + // Check if workspace package was updated + const appPackageJson = await Bun.file(join(dir, "packages/app/package.json")).json(); + expect(appPackageJson.dependencies["no-deps"]).toBe("2.0.0"); + }); + + it("should handle catalog updates correctly", async () => { + const dir = tempDirWithFiles("update-interactive-catalog-actual", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "no-deps": "1.0.0", // Old version in catalog + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + version: "1.0.0", + dependencies: { + "no-deps": "catalog:", + }, + }), + }); + + // First install + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const stdout = await new Response(update.stdout).text(); + const stderr = await new Response(update.stderr).text(); + + expect(exitCode).toBe(0); + expect(stdout + stderr).not.toContain("panic"); + expect(stdout + stderr).not.toContain("catalog: failed to resolve"); + + // Check if catalog was updated in root package.json + const rootPackageJson = await Bun.file(join(dir, "package.json")).json(); + expect(rootPackageJson.catalog["no-deps"]).toBe("2.0.0"); + + // App package.json should still have catalog reference + const appPackageJson = await Bun.file(join(dir, "packages/app/package.json")).json(); + expect(appPackageJson.dependencies["no-deps"]).toBe("catalog:"); + }); + + it("should work correctly when run from inside a workspace directory", async () => { + const dir = tempDirWithFiles("update-interactive-from-workspace", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + }), + "packages/app1/package.json": JSON.stringify({ + name: "@test/app1", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + }, + }), + "packages/app2/package.json": JSON.stringify({ + name: "@test/app2", + version: "1.0.0", + dependencies: { + "dep-with-tags": "1.0.0", + }, + }), + }); + + // First install from root + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update from inside workspace + const workspaceDir = join(dir, "packages/app1"); + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: workspaceDir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + const stderr = await new Response(update.stderr).text(); + const combined = output + stderr; + + // Should not fail with FileNotFound + expect(exitCode).toBe(0); + expect(combined).not.toContain("FileNotFound"); + expect(combined).not.toContain("Failed to update"); + + // Check that both workspace packages were updated + const app1Json = await Bun.file(join(dir, "packages/app1/package.json")).json(); + const app2Json = await Bun.file(join(dir, "packages/app2/package.json")).json(); + + expect(app1Json.dependencies["no-deps"]).toBe("2.0.0"); + expect(app2Json.dependencies["dep-with-tags"]).toBe("3.0.0"); + }); + + it("should handle basic interactive update with select all", async () => { + const dir = tempDirWithFiles("update-interactive-basic", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check if package was updated + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.dependencies["no-deps"]).toBe("2.0.0"); + }); + + it("should preserve version prefixes for all semver range types in catalogs", async () => { + const dir = tempDirWithFiles("update-interactive-semver-prefixes", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "no-deps": "^1.0.0", + "dep-with-tags": "~1.0.0", + "a-dep": ">=1.0.5", + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "catalog:", + "dep-with-tags": "catalog:", + "a-dep": "catalog:", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check if prefixes were preserved + const packageJson = await Bun.file(join(dir, "package.json")).json(); + + // All prefixes should be preserved (versions may or may not change) + expect(packageJson.catalog["no-deps"]).toMatch(/^\^/); + expect(packageJson.catalog["dep-with-tags"]).toMatch(/^~/); + expect(packageJson.catalog["a-dep"]).toMatch(/^>=/); + }); + + it("should handle catalog updates in workspaces.catalogs object", async () => { + const dir = tempDirWithFiles("update-interactive-workspaces-catalogs", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: { + packages: ["packages/*"], + catalogs: { + "tools": { + "no-deps": "^1.0.0", + "dep-with-tags": "~1.0.0", + }, + "frameworks": { + "a-dep": "^1.0.5", + "normal-dep-and-dev-dep": "^1.0.0", + }, + }, + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "catalog:tools", + "a-dep": "catalog:frameworks", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Installing updates..."); + + // Check if catalogs were updated correctly + const packageJson = await Bun.file(join(dir, "package.json")).json(); + + // Prefixes should be preserved + expect(packageJson.workspaces.catalogs.tools["no-deps"]).toMatch(/^\^/); + expect(packageJson.workspaces.catalogs.tools["dep-with-tags"]).toMatch(/^~/); + }); + + it("should handle mixed workspace and catalog dependencies", async () => { + const dir = tempDirWithFiles("update-interactive-mixed-deps", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "no-deps": "^1.0.0", + }, + }), + "packages/lib/package.json": JSON.stringify({ + name: "@test/lib", + version: "1.0.0", + dependencies: { + "a-dep": "^1.0.5", + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "@test/lib": "workspace:*", + "no-deps": "catalog:", + "dep-with-tags": "~1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check updates were applied correctly + const appJson = await Bun.file(join(dir, "packages/app/package.json")).json(); + const libJson = await Bun.file(join(dir, "packages/lib/package.json")).json(); + + // Workspace dependency should remain unchanged + expect(appJson.dependencies["@test/lib"]).toBe("workspace:*"); + + // Regular dependencies should be updated with prefix preserved + expect(appJson.dependencies["dep-with-tags"]).toMatch(/^~/); + expect(libJson.dependencies["a-dep"]).toMatch(/^\^/); + }); + + it("should handle selecting specific packages in interactive mode", async () => { + const dir = tempDirWithFiles("update-interactive-selective", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + "dep-with-tags": "1.0.0", + "a-dep": "1.0.5", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update that selects only first package (space toggles, arrow down, enter) + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send keyboard navigation: space to toggle, arrow down, enter to confirm + update.stdin.write(" \u001b[B\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Selected 1 package to update"); + + // Check only one package was updated + const packageJson = await Bun.file(join(dir, "package.json")).json(); + + // Since we toggled only the first package, check that only one was updated + // The actual package updated depends on the order, so we check that exactly one changed + let updatedCount = 0; + if (packageJson.dependencies["no-deps"] !== "1.0.0") updatedCount++; + if (packageJson.dependencies["dep-with-tags"] !== "1.0.0") updatedCount++; + if (packageJson.dependencies["a-dep"] !== "1.0.5") updatedCount++; + expect(updatedCount).toBe(1); + }); + + it("should handle empty catalog definitions gracefully", async () => { + const dir = tempDirWithFiles("update-interactive-empty-catalog", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: {}, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "^1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check workspace package was updated normally + const appJson = await Bun.file(join(dir, "packages/app/package.json")).json(); + expect(appJson.dependencies["no-deps"]).toBe("^2.0.0"); + + // Root catalog should remain empty + const rootJson = await Bun.file(join(dir, "package.json")).json(); + expect(Object.keys(rootJson.catalog)).toHaveLength(0); + }); + + it("should handle cancellation (Ctrl+C) gracefully", async () => { + const dir = tempDirWithFiles("update-interactive-cancel", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update and send Ctrl+C + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send Ctrl+C to cancel + update.stdin.write("\u0003"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Cancelled"); + + // Check package.json was not modified + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.dependencies["no-deps"]).toBe("1.0.0"); + }); + + it("should handle packages with pre-release versions correctly", async () => { + const dir = tempDirWithFiles("update-interactive-prerelease", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + "dep-with-tags": "^1.0.0", + "a-dep": "~1.0.5", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check version prefixes are preserved + const packageJson = await Bun.file(join(dir, "package.json")).json(); + + // Prefixes should be preserved + expect(packageJson.dependencies["dep-with-tags"]).toMatch(/^\^/); + expect(packageJson.dependencies["a-dep"]).toMatch(/^~/); + }); + + it("should update catalog in workspaces object (not workspaces.catalogs)", async () => { + const dir = tempDirWithFiles("update-interactive-workspaces-catalog", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: { + packages: ["packages/*"], + catalog: { + "no-deps": "^1.0.0", + "dep-with-tags": "~1.0.0", + }, + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "catalog:", + "dep-with-tags": "catalog:", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Installing updates..."); + + // Check catalog was updated with preserved prefixes + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.workspaces.catalog["no-deps"]).toBe("^2.0.0"); + expect(packageJson.workspaces.catalog["dep-with-tags"]).toMatch(/^~/); + }); + + it("should handle scoped packages in catalogs correctly", async () => { + const dir = tempDirWithFiles("update-interactive-scoped-catalog", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "@scoped/has-bin-entry": "^1.0.0", + "no-deps": "~1.0.0", + "dep-with-tags": ">=1.0.0", + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "@scoped/has-bin-entry": "catalog:", + "no-deps": "catalog:", + "dep-with-tags": "catalog:", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check scoped packages were updated with preserved prefixes + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.catalog["@scoped/has-bin-entry"]).toMatch(/^\^/); + expect(packageJson.catalog["no-deps"]).toMatch(/^~/); + expect(packageJson.catalog["dep-with-tags"]).toMatch(/^>=/); + }); + + it("should handle catalog updates when running from root with filter", async () => { + const dir = tempDirWithFiles("update-interactive-filter-catalog", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "no-deps": "^1.0.0", + "dep-with-tags": "~1.0.0", + }, + }), + "packages/app1/package.json": JSON.stringify({ + name: "@test/app1", + dependencies: { + "no-deps": "catalog:", + }, + }), + "packages/app2/package.json": JSON.stringify({ + name: "@test/app2", + dependencies: { + "dep-with-tags": "catalog:", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with filter + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--filter=@test/app2", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + + // Check catalog was updated + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.catalog["dep-with-tags"]).toMatch(/^~/); + //todo: actually check the catalog was updated + }); + + it("should handle multiple catalog definitions with same package", async () => { + const dir = tempDirWithFiles("update-interactive-multi-catalog", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: { + packages: ["packages/*"], + catalogs: { + "dev": { + "no-deps": "^1.0.0", + }, + "prod": { + "no-deps": "~1.0.0", + }, + }, + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "catalog:prod", + }, + devDependencies: { + "no-deps": "catalog:dev", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + + // Check both catalogs were updated with preserved prefixes + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.workspaces.catalogs.dev["no-deps"]).toBe("^2.0.0"); + expect(packageJson.workspaces.catalogs.prod["no-deps"]).toMatch(/^~/); + //todo: actually check the catalog was updated + }); + + it("should handle version ranges with multiple conditions", async () => { + const dir = tempDirWithFiles("update-interactive-complex-ranges", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "no-deps": "^1.0.0 || ^2.0.0", + "dep-with-tags": ">=1.0.0 <3.0.0", + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "catalog:", + "dep-with-tags": "catalog:", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with piped input + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Check complex ranges are handled (they might be simplified) + const packageJson = await Bun.file(join(dir, "package.json")).json(); + // Complex ranges might be simplified to latest version + expect(packageJson.catalog["no-deps"]).toBeDefined(); + expect(packageJson.catalog["dep-with-tags"]).toBeDefined(); + }); + + it("should handle dry-run mode correctly", async () => { + const dir = tempDirWithFiles("update-interactive-dry-run", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + "dep-with-tags": "1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with dry-run + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest", "--dry-run"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Selected"); + + // Check packages were NOT updated (dry-run) + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.dependencies["no-deps"]).toBe("1.0.0"); + expect(packageJson.dependencies["dep-with-tags"]).toBe("1.0.0"); + }); + + it("should handle keyboard navigation correctly", async () => { + const dir = tempDirWithFiles("update-interactive-navigation", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + "dep-with-tags": "1.0.0", + "a-dep": "1.0.5", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update with keyboard navigation: + // - n (select none) + // - i (invert selection) + // - Enter (confirm) + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send keyboard navigation commands + update.stdin.write("ni\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Selected 3 packages to update"); + }); + + // Comprehensive tests from separate file + it("comprehensive interactive update test with all scenarios", async () => { + const dir = tempDirWithFiles("update-interactive-comprehensive", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + // Root package.json with catalog definitions and dependencies + "package.json": JSON.stringify({ + name: "root-project", + version: "1.0.0", + private: true, + workspaces: ["packages/*"], + // Catalog with old versions that can be updated + catalog: { + "no-deps": "^1.0.0", + "dep-with-tags": "~1.0.0", + }, + // Some root dependencies + dependencies: { + "a-dep": "^1.0.5", + }, + devDependencies: { + "normal-dep-and-dev-dep": "^1.0.0", + }, + }), + // Workspace 1: Uses catalog references and has its own dependencies + "packages/app1/package.json": JSON.stringify({ + name: "@test/app1", + version: "1.0.0", + dependencies: { + "no-deps": "catalog:", // References catalog + "dep-with-tags": "catalog:", // References catalog + "a-dep": "^1.0.5", // Regular dependency (same as root) + }, + devDependencies: { + "normal-dep-and-dev-dep": "^1.0.0", // Dev dependency + }, + }), + // Workspace 2: Different dependencies to test workspace-specific updates + "packages/app2/package.json": JSON.stringify({ + name: "@test/app2", + version: "1.0.0", + dependencies: { + "no-deps": "catalog:", // References catalog + "a-dep": "^1.0.5", // Regular dependency + }, + devDependencies: { + "dep-with-tags": "^1.0.0", // Different from catalog - should update independently + }, + }), + }); + + // First install to establish the lockfile + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const installExitCode = await install.exited; + if (installExitCode !== 0) { + const stderr = await new Response(install.stderr).text(); + console.error("Install failed:", stderr); + } + expect(installExitCode).toBe(0); + + // Run interactive update and select all packages + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + // Send 'a' to select all, then newline to confirm + update.stdin.write("a\n"); + update.stdin.end(); + + const updateExitCode = await update.exited; + const stdout = await new Response(update.stdout).text(); + const stderr = await new Response(update.stderr).text(); + const combined = stdout + stderr; + + // Should complete successfully + expect(updateExitCode).toBe(0); + expect(combined).not.toContain("panic"); + expect(combined).not.toContain("FileNotFound"); + expect(combined).not.toContain("Failed to update"); + + // Verify catalog definitions were updated in root package.json + const rootPackageJson = await Bun.file(join(dir, "package.json")).json(); + + // Catalog should be updated while preserving prefixes + expect(rootPackageJson.catalog["no-deps"]).toBe("^2.0.0"); + expect(rootPackageJson.catalog["dep-with-tags"]).toMatch(/^~/); + + // Root dependencies should be updated + expect(rootPackageJson.dependencies["a-dep"]).toMatch(/^\^/); + expect(rootPackageJson.devDependencies["normal-dep-and-dev-dep"]).toMatch(/^\^/); + + // App1 should have catalog references preserved but regular deps updated + const app1Json = await Bun.file(join(dir, "packages/app1/package.json")).json(); + expect(app1Json.dependencies["no-deps"]).toBe("catalog:"); // Catalog ref preserved + expect(app1Json.dependencies["dep-with-tags"]).toBe("catalog:"); // Catalog ref preserved + expect(app1Json.dependencies["a-dep"]).toMatch(/^\^/); // Regular dep updated + expect(app1Json.devDependencies["normal-dep-and-dev-dep"]).toMatch(/^\^/); // Dev dep updated + + // App2 should have catalog references preserved and independent deps updated + const app2Json = await Bun.file(join(dir, "packages/app2/package.json")).json(); + expect(app2Json.dependencies["no-deps"]).toBe("catalog:"); // Catalog ref preserved + expect(app2Json.dependencies["a-dep"]).toMatch(/^\^/); // Regular dep updated + expect(app2Json.devDependencies["dep-with-tags"]).toMatch(/^\^/); // Independent dep updated + + // Verify lockfile exists and is valid + console.log("Checking lockfile..."); + const lockfilePath = join(dir, "bun.lock"); + const lockfileExists = await Bun.file(lockfilePath).exists(); + expect(lockfileExists).toBe(true); + + // Run bun install again to verify no changes are needed + await using verifyInstall = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const verifyExitCode = await verifyInstall.exited; + const verifyStdout = await new Response(verifyInstall.stdout).text(); + const verifyStderr = await new Response(verifyInstall.stderr).text(); + const verifyCombined = verifyStdout + verifyStderr; + + expect(verifyExitCode).toBe(0); + + // Should indicate no changes are needed - just check that no new packages are being installed + expect(verifyCombined).not.toContain("Installing"); + // "Saved lockfile" is fine even when no changes, so don't check for it + }); + + it("interactive update with workspace filters", async () => { + const dir = tempDirWithFiles("update-interactive-filter", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + private: true, + workspaces: ["packages/*"], + catalog: { + "no-deps": "^1.0.0", + }, + }), + "packages/frontend/package.json": JSON.stringify({ + name: "@test/frontend", + dependencies: { + "no-deps": "catalog:", + "a-dep": "^1.0.5", + }, + }), + "packages/backend/package.json": JSON.stringify({ + name: "@test/backend", + dependencies: { + "dep-with-tags": "^1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Update only frontend workspace + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--filter=@test/frontend", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Verify catalog was updated (even with filter) + const rootJson = await Bun.file(join(dir, "package.json")).json(); + expect(rootJson.catalog["no-deps"]).toBe("^2.0.0"); + + // Verify frontend was updated + const frontendJson = await Bun.file(join(dir, "packages/frontend/package.json")).json(); + expect(frontendJson.dependencies["a-dep"]).toMatch(/^\^/); + + // Verify backend was not updated (should still be old version) + const backendJson = await Bun.file(join(dir, "packages/backend/package.json")).json(); + expect(backendJson.dependencies["dep-with-tags"]).toBe("^1.0.0"); + }); + + it("interactive update with workspaces.catalogs structure", async () => { + const dir = tempDirWithFiles("update-interactive-workspaces-catalogs", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "root", + version: "1.0.0", + workspaces: { + packages: ["packages/*"], + catalogs: { + "shared": { + "no-deps": "^1.0.0", + "dep-with-tags": "~1.0.0", + }, + "tools": { + "a-dep": ">=1.0.5", + }, + }, + }, + }), + "packages/app/package.json": JSON.stringify({ + name: "@test/app", + dependencies: { + "no-deps": "catalog:shared", + "dep-with-tags": "catalog:shared", + "a-dep": "catalog:tools", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Installing updates..."); // Should show install message + + // Verify workspaces.catalogs were updated with preserved prefixes AND new versions + const packageJson = await Bun.file(join(dir, "package.json")).json(); + + // Check that versions actually changed from original static values + expect(packageJson.workspaces.catalogs.shared["no-deps"]).not.toBe("^1.0.0"); // Should be newer + expect(packageJson.workspaces.catalogs.shared["dep-with-tags"]).not.toBe("~1.0.0"); // Should be newer + + // For a-dep, check if it changed or at least verify it has the right prefix + // (Some versions might not change if already satisfied) + const aDep = packageJson.workspaces.catalogs.tools["a-dep"]; + if (aDep !== ">=1.0.5") { + // Version changed - verify it starts with >= + expect(aDep).toMatch(/^>=/); + } else { + // Version didn't change - that's ok if the constraint was already satisfied + expect(aDep).toBe(">=1.0.5"); + } + + // Check that prefixes are preserved + expect(packageJson.workspaces.catalogs.shared["no-deps"]).toMatch(/^\^/); + expect(packageJson.workspaces.catalogs.shared["dep-with-tags"]).toMatch(/^~/); + expect(packageJson.workspaces.catalogs.tools["a-dep"]).toMatch(/^>=/); + + // App package should still have catalog references (unchanged) + const appJson = await Bun.file(join(dir, "packages/app/package.json")).json(); + expect(appJson.dependencies["no-deps"]).toBe("catalog:shared"); + expect(appJson.dependencies["dep-with-tags"]).toBe("catalog:shared"); + expect(appJson.dependencies["a-dep"]).toBe("catalog:tools"); + }); + + it("interactive update dry run mode", async () => { + const dir = tempDirWithFiles("update-interactive-dry-run", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + dependencies: { + "no-deps": "1.0.0", + "dep-with-tags": "1.0.0", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Store original package.json content + const originalContent = await Bun.file(join(dir, "package.json")).text(); + + // Run interactive update with dry-run + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "--latest", "--dry-run"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + const output = await new Response(update.stdout).text(); + + expect(exitCode).toBe(0); + expect(output).toContain("Dry run"); + + // Verify package.json was NOT modified + const afterContent = await Bun.file(join(dir, "package.json")).text(); + expect(afterContent).toBe(originalContent); + + // Parse and verify versions are still old + const packageJson = await Bun.file(join(dir, "package.json")).json(); + expect(packageJson.dependencies["no-deps"]).toBe("1.0.0"); + expect(packageJson.dependencies["dep-with-tags"]).toBe("1.0.0"); + }); + + it("interactive update with mixed dependency types", async () => { + const dir = tempDirWithFiles("update-interactive-mixed", { + "bunfig.toml": `[install] +cache = false +registry = "${registryUrl}" +`, + "package.json": JSON.stringify({ + name: "test-project", + version: "1.0.0", + workspaces: ["packages/*"], + catalog: { + "a-dep": "^1.0.5", + }, + dependencies: { + "no-deps": "^1.0.0", + }, + devDependencies: { + "dep-with-tags": "~1.0.0", + }, + peerDependencies: { + "a-dep": ">=1.0.5", + }, + optionalDependencies: { + "normal-dep-and-dev-dep": "^1.0.0", + }, + }), + "packages/workspace1/package.json": JSON.stringify({ + name: "@test/workspace1", + dependencies: { + "a-dep": "catalog:", + "@test/workspace2": "workspace:*", // Workspace dependency + }, + devDependencies: { + "no-deps": "^1.0.0", + }, + }), + "packages/workspace2/package.json": JSON.stringify({ + name: "@test/workspace2", + version: "1.0.0", + dependencies: { + "a-dep": "catalog:", + }, + }), + }); + + // Install first + await using install = Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: dir, + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(await install.exited).toBe(0); + + // Run interactive update + await using update = Bun.spawn({ + cmd: [bunExe(), "update", "-i", "-r", "--latest"], + cwd: dir, + env: bunEnv, + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + }); + + update.stdin.write("a\n"); + update.stdin.end(); + + const exitCode = await update.exited; + expect(exitCode).toBe(0); + + // Verify all dependency types were handled correctly + const rootJson = await Bun.file(join(dir, "package.json")).json(); + expect(rootJson.catalog["a-dep"]).toMatch(/^\^/); // Catalog updated + expect(rootJson.dependencies["no-deps"]).toMatch(/^\^/); // Regular dep updated + expect(rootJson.devDependencies["dep-with-tags"]).toMatch(/^~/); // Dev dep updated with prefix preserved + expect(rootJson.peerDependencies["a-dep"]).toMatch(/^>=/); // Peer dep updated with prefix preserved + expect(rootJson.optionalDependencies["normal-dep-and-dev-dep"]).toMatch(/^\^/); // Optional dep updated + + // Verify workspace dependencies + const ws1Json = await Bun.file(join(dir, "packages/workspace1/package.json")).json(); + expect(ws1Json.dependencies["a-dep"]).toBe("catalog:"); // Catalog ref preserved + expect(ws1Json.dependencies["@test/workspace2"]).toBe("workspace:*"); // Workspace ref preserved + expect(ws1Json.devDependencies["no-deps"]).toMatch(/^\^/); // Regular dep updated + + const ws2Json = await Bun.file(join(dir, "packages/workspace2/package.json")).json(); + expect(ws2Json.dependencies["a-dep"]).toBe("catalog:"); // Catalog ref preserved + }); }); diff --git a/test/harness.ts b/test/harness.ts index 474c666155..2b698e73a5 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -883,28 +883,36 @@ export async function describeWithContainer( let containerId: string; { const envs = Object.entries(env).map(([k, v]) => `-e${k}=${v}`); - const { exitCode, stdout, stderr } = Bun.spawnSync({ + const { exitCode, stdout, stderr, signalCode } = Bun.spawnSync({ cmd: [docker, "run", "--rm", "-dPit", ...envs, image, ...args], stdout: "pipe", stderr: "pipe", }); if (exitCode !== 0) { process.stderr.write(stderr); - test.skip(`docker container for ${image} failed to start`, () => {}); + test.skip(`docker container for ${image} failed to start (exit: ${exitCode})`, () => {}); + return false; + } + if (signalCode) { + test.skip(`docker container for ${image} failed to start (signal: ${signalCode})`, () => {}); return false; } containerId = stdout.toString("utf-8").trim(); } let port: number; { - const { exitCode, stdout, stderr } = Bun.spawnSync({ + const { exitCode, stdout, stderr, signalCode } = Bun.spawnSync({ cmd: [docker, "port", containerId], stdout: "pipe", stderr: "pipe", }); if (exitCode !== 0) { process.stderr.write(stderr); - test.skip(`docker container for ${image} failed to find a port`, () => {}); + test.skip(`docker container for ${image} failed to find a port (exit: ${exitCode})`, () => {}); + return false; + } + if (signalCode) { + test.skip(`docker container for ${image} failed to find a port (signal: ${signalCode})`, () => {}); return false; } const [firstPort] = stdout diff --git a/test/integration/bun-types/bun-types.test.ts b/test/integration/bun-types/bun-types.test.ts index 9095ab1681..794dca6194 100644 --- a/test/integration/bun-types/bun-types.test.ts +++ b/test/integration/bun-types/bun-types.test.ts @@ -56,7 +56,7 @@ beforeAll(async () => { cd ${BUN_TYPES_PACKAGE_ROOT} bun run build bun pm pack --destination ${FIXTURE_DIR} - exit 0 + rm CLAUDE.md mv package.json.backup package.json cd ${FIXTURE_DIR} @@ -140,6 +140,14 @@ async function diagnose( const program = service.getProgram(); if (!program) throw new Error("Failed to create program"); + function getLine(diagnostic: ts.Diagnostic) { + if (!diagnostic.file) return null; + if (diagnostic.start === undefined) return null; + + const lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); + return `${relative(fixtureDir, diagnostic.file.fileName)}:${lineAndCharacter.line + 1}:${lineAndCharacter.character + 1}`; + } + const diagnostics = ts .getPreEmitDiagnostics(program) .concat(program.getOptionsDiagnostics()) @@ -148,19 +156,18 @@ async function diagnose( .concat(program.getDeclarationDiagnostics()) .concat(program.emit().diagnostics) .map(diagnostic => ({ - category: ts.DiagnosticCategory[diagnostic.category], - file: diagnostic.file?.fileName ? relative(fixtureDir, diagnostic.file?.fileName) : null, + line: getLine(diagnostic), message: typeof diagnostic.messageText === "string" ? diagnostic.messageText : diagnostic.messageText.messageText, code: diagnostic.code, })); return { diagnostics, - emptyInterfaces: checkForEmptyInterfaces(program, fixtureDir), + emptyInterfaces: checkForEmptyInterfaces(program), }; } -function checkForEmptyInterfaces(program: ts.Program, fixtureDir: string) { +function checkForEmptyInterfaces(program: ts.Program) { const empties = new Set(); const checker = program.getTypeChecker(); @@ -179,7 +186,6 @@ function checkForEmptyInterfaces(program: ts.Program, fixtureDir: string) { const concernsBun = declarations.some(decl => decl.getSourceFile().fileName.includes("node_modules/@types/bun")); if (!concernsBun) { - // the lion is not concerned by symbols outside of bun continue; } @@ -225,7 +231,8 @@ afterAll(async () => { console.log(TEMP_DIR); if (Bun.env.TYPES_INTEGRATION_TEST_KEEP_TEMP_DIR === "true") { - console.log(`Keeping temp dir ${TEMP_DIR} for debugging`); + console.log(`Keeping temp dir ${TEMP_DIR}/fixture for debugging`); + await cp(TSCONFIG_SOURCE_PATH, join(TEMP_DIR, "fixture", "tsconfig.json")); } else { await rm(TEMP_DIR, { recursive: true, force: true }); } @@ -278,6 +285,17 @@ describe("@types/bun integration test", () => { }); }); + test("checks with no lib at all", async () => { + const { diagnostics, emptyInterfaces } = await diagnose(FIXTURE_DIR, { + options: { + lib: [], + }, + }); + + expect(emptyInterfaces).toEqual(new Set()); + expect(diagnostics).toEqual([]); + }); + test("checks with lib.dom.d.ts", async () => { const { diagnostics, emptyInterfaces } = await diagnose(FIXTURE_DIR, { options: { @@ -288,204 +306,186 @@ describe("@types/bun integration test", () => { expect(emptyInterfaces).toEqual(new Set()); expect(diagnostics).toEqual([ { - category: "Error", - file: "globals.ts", + code: 2769, + line: "fetch.ts:25:32", + message: "No overload matches this call.", + }, + { + code: 2769, + line: "fetch.ts:33:32", + message: "No overload matches this call.", + }, + { + code: 2769, + line: "fetch.ts:168:34", + message: "No overload matches this call.", + }, + { + line: "globals.ts:307:5", message: "Object literal may only specify known properties, and 'headers' does not exist in type 'string[]'.", code: 2353, }, { - category: "Error", - file: "http.ts", + line: "http.ts:43:24", message: "Argument of type '() => AsyncGenerator | \"hey\", void, unknown>' is not assignable to parameter of type 'BodyInit | null | undefined'.", code: 2345, }, { - category: "Error", - file: "http.ts", + line: "http.ts:55:24", message: "Argument of type 'AsyncGenerator | \"it works!\", void, unknown>' is not assignable to parameter of type 'BodyInit | null | undefined'.", code: 2345, }, { - category: "Error", - file: "index.ts", + line: "index.ts:193:14", message: "Argument of type 'AsyncGenerator, void, unknown>' is not assignable to parameter of type 'BodyInit | null | undefined'.", code: 2345, }, { - category: "Error", - file: "index.ts", + line: "index.ts:323:29", message: "Argument of type '{ headers: { \"x-bun\": string; }; }' is not assignable to parameter of type 'number'.", code: 2345, }, { - category: "Error", - file: "spawn.ts", - message: "Property 'text' does not exist on type 'ReadableStream>'.", + line: "spawn.ts:62:38", + message: "Property 'text' does not exist on type 'ReadableStream>'.", code: 2339, }, { - category: "Error", - file: "spawn.ts", - message: "Property 'text' does not exist on type 'ReadableStream>'.", + line: "spawn.ts:107:38", + message: "Property 'text' does not exist on type 'ReadableStream>'.", code: 2339, }, { - category: "Error", - file: "streams.ts", + line: "streams.ts:16:3", message: "No overload matches this call.", code: 2769, }, { - category: "Error", - file: "streams.ts", + line: "streams.ts:18:16", message: "Property 'write' does not exist on type 'ReadableByteStreamController'.", code: 2339, }, { - category: "Error", - file: "streams.ts", + line: "streams.ts:44:19", message: "Property 'json' does not exist on type 'ReadableStream>'.", code: 2339, }, { - category: "Error", - file: "streams.ts", + line: "streams.ts:45:19", message: "Property 'bytes' does not exist on type 'ReadableStream>'.", code: 2339, }, { - category: "Error", - file: "streams.ts", + line: "streams.ts:46:19", message: "Property 'text' does not exist on type 'ReadableStream>'.", code: 2339, }, { - category: "Error", - file: "streams.ts", + line: "streams.ts:47:19", message: "Property 'blob' does not exist on type 'ReadableStream>'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:25:5", message: "Object literal may only specify known properties, and 'protocols' does not exist in type 'string[]'.", code: 2353, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:30:5", message: "Object literal may only specify known properties, and 'protocol' does not exist in type 'string[]'.", code: 2353, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:35:5", message: "Object literal may only specify known properties, and 'protocol' does not exist in type 'string[]'.", code: 2353, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:43:5", message: "Object literal may only specify known properties, and 'headers' does not exist in type 'string[]'.", code: 2353, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:51:5", message: "Object literal may only specify known properties, and 'protocols' does not exist in type 'string[]'.", code: 2353, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:185:29", message: "Expected 2 arguments, but got 0.", code: 2554, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:192:17", message: "Property 'URL' does not exist on type 'WebSocket'. Did you mean 'url'?", code: 2551, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:196:3", message: "Type '\"nodebuffer\"' is not assignable to type 'BinaryType'.", code: 2322, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:242:6", message: "Property 'ping' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:245:6", message: "Property 'ping' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:249:6", message: "Property 'ping' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:253:6", message: "Property 'ping' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:256:6", message: "Property 'pong' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:259:6", message: "Property 'pong' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:263:6", message: "Property 'pong' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:267:6", message: "Property 'pong' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "websocket.ts", + line: "websocket.ts:270:6", message: "Property 'terminate' does not exist on type 'WebSocket'.", code: 2339, }, { - category: "Error", - file: "worker.ts", + line: "worker.ts:23:11", message: "Property 'ref' does not exist on type 'Worker'.", code: 2339, }, { - category: "Error", - file: "worker.ts", + line: "worker.ts:24:11", message: "Property 'unref' does not exist on type 'Worker'.", code: 2339, }, { - category: "Error", - file: "worker.ts", + line: "worker.ts:25:11", message: "Property 'threadId' does not exist on type 'Worker'.", code: 2339, }, diff --git a/test/integration/bun-types/fixture/array-buffer.ts b/test/integration/bun-types/fixture/array-buffer.ts index a3253138e3..7dcf9c4db3 100644 --- a/test/integration/bun-types/fixture/array-buffer.ts +++ b/test/integration/bun-types/fixture/array-buffer.ts @@ -1,3 +1,5 @@ +import { expectType } from "./utilities"; + const buffer = new ArrayBuffer(1024, { maxByteLength: 2048, }); @@ -9,3 +11,5 @@ TextDecoder; const buf = new SharedArrayBuffer(1024); buf.grow(2048); + +expectType(buffer[Symbol.toStringTag]).extends(); diff --git a/test/integration/bun-types/fixture/atomics.ts b/test/integration/bun-types/fixture/atomics.ts new file mode 100644 index 0000000000..54ab902f71 --- /dev/null +++ b/test/integration/bun-types/fixture/atomics.ts @@ -0,0 +1,40 @@ +// Test Atomics global type definitions with TypeScript +declare const buffer: SharedArrayBuffer; +declare const view: Int32Array; +declare const view16: Int16Array; +declare const view8: Int8Array; +declare const viewU32: Uint32Array; +declare const bigView: BigInt64Array; + +// Test basic Atomics operations - type signatures only +const stored: number = Atomics.store(view, 0, 42); +const loaded: number = Atomics.load(view, 0); +const added: number = Atomics.add(view, 0, 8); +const subtracted: number = Atomics.sub(view, 0, 5); + +// Test compare and exchange operations +const exchanged: number = Atomics.compareExchange(view, 0, 50, 100); +const swapped: number = Atomics.exchange(view, 0, 200); + +// Test bitwise operations +const anded: number = Atomics.and(view, 0, 0xFF); +const ored: number = Atomics.or(view, 0, 0x10); +const xored: number = Atomics.xor(view, 0, 0x0F); + +// Test utility functions +const lockFree4: boolean = Atomics.isLockFree(4); +const lockFree8: boolean = Atomics.isLockFree(8); + +// Test synchronization primitives +const waitResult: "ok" | "not-equal" | "timed-out" = Atomics.wait(view, 0, 0, 1000); +const notified: number = Atomics.notify(view, 0, 1); + +// Test with different integer TypedArray types +const stored16: number = Atomics.store(view16, 0, 42); +const loaded8: number = Atomics.load(view8, 0); +const addedU32: number = Atomics.add(viewU32, 0, 1); + +// Test BigInt64Array support +const storedBig: bigint = Atomics.store(bigView, 0, 42n); +const loadedBig: bigint = Atomics.load(bigView, 0); +const addedBig: bigint = Atomics.add(bigView, 0, 8n); \ No newline at end of file diff --git a/test/integration/bun-types/fixture/fetch.ts b/test/integration/bun-types/fixture/fetch.ts new file mode 100644 index 0000000000..32197ce37c --- /dev/null +++ b/test/integration/bun-types/fixture/fetch.ts @@ -0,0 +1,248 @@ +// Valid body types +fetch("https://example.com", { body: "string body" }); +fetch("https://example.com", { body: JSON.stringify({ key: "value" }) }); +fetch("https://example.com", { body: new Blob(["blob content"]) }); +fetch("https://example.com", { body: new File(["file content"], "file.txt") }); +fetch("https://example.com", { body: new ArrayBuffer(8) }); +fetch("https://example.com", { body: new Uint8Array([1, 2, 3, 4]) }); +fetch("https://example.com", { body: new Int32Array([1, 2, 3, 4]) }); +fetch("https://example.com", { body: new DataView(new ArrayBuffer(8)) }); +fetch("https://example.com", { body: new URLSearchParams({ key: "value" }) }); +fetch("https://example.com", { body: new FormData() }); +fetch("https://example.com", { body: new ReadableStream() }); +fetch("https://example.com", { body: Buffer.from("buffer content") }); +fetch("https://example.com", { body: Bun.file("path") }); +fetch("https://example.com", { body: Bun.file("hey").stream() }); +fetch("https://example.com", { body: new Response("bun").body }); +fetch("https://example.com", { body: Bun.s3.file("hey") }); +fetch("https://example.com", { body: Bun.s3.file("hey").stream() }); +fetch("https://example.com", { body: Bun.s3.file("hey").readable }); + +async function* asyncGenerator() { + yield "chunk1"; + yield "chunk2"; +} +fetch("https://example.com", { body: asyncGenerator() }); + +const asyncIterable = { + async *[Symbol.asyncIterator]() { + yield "data1"; + yield "data2"; + }, +}; +fetch("https://example.com", { body: asyncIterable }); + +fetch("https://example.com").then(res => { + fetch("https://example.com", { body: res.body }); +}); + +const req = new Request("https://example.com", { body: "request body" }); +fetch("https://example.com", { body: req.body }); + +fetch("https://example.com", { body: null }); +fetch("https://example.com", { body: undefined }); +fetch("https://example.com", {}); // No body + +{ + function* syncGenerator() { + yield new Uint8Array([1, 2, 3]); + yield new Uint8Array([4, 5, 6]); + } + // @ts-expect-error Unsupported + fetch("https://example.com", { body: syncGenerator() }); +} + +{ + const iterable = { + *[Symbol.iterator]() { + yield new Uint8Array([7, 8, 9]); + }, + }; + // @ts-expect-error normal iterators are not supported + fetch("https://example.com", { body: iterable }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: 123 }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: true }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: false }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: { plain: "object" } }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: ["array", "of", "strings"] }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: new Date() }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: /regex/ }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: Symbol("symbol") }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: BigInt(123) }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: new Map() }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: new Set() }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: new WeakMap() }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: new WeakSet() }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: Promise.resolve("promise") }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: () => "function" }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: class MyClass {} }); +} + +{ + // @ts-expect-error + fetch("https://example.com", { body: new Error("error") }); +} + +{ + fetch("https://example.com", { method: "GET", body: "should not have body but types should still allow it" }); + fetch("https://example.com", { method: "HEAD", body: "should not have body but types should still allow it" }); +} + +{ + const multipartForm = new FormData(); + multipartForm.append("field1", "value1"); + multipartForm.append("file", new File(["content"], "test.txt")); + fetch("https://example.com", { body: multipartForm }); +} +{ + const searchParams = new URLSearchParams(); + searchParams.append("key1", "value1"); + searchParams.append("key2", "value2"); + fetch("https://example.com", { body: searchParams }); +} +{ + fetch("https://example.com", { body: new SharedArrayBuffer(16) }); +} + +{ + fetch("https://example.com", { body: new Float32Array([1.1, 2.2, 3.3]) }); + fetch("https://example.com", { body: new Float64Array([1.1, 2.2, 3.3]) }); + fetch("https://example.com", { body: new Int8Array([-128, 0, 127]) }); + fetch("https://example.com", { body: new Uint16Array([0, 32768, 65535]) }); + fetch("https://example.com", { body: new BigInt64Array([BigInt(1), BigInt(2)]) }); + fetch("https://example.com", { body: new BigUint64Array([BigInt(1), BigInt(2)]) }); +} + +{ + const textStream = new ReadableStream({ + start(controller) { + controller.enqueue("chunk1"); + controller.enqueue("chunk2"); + controller.close(); + }, + }); + fetch("https://example.com", { body: textStream }); +} + +{ + const byteStream = new ReadableStream>({ + start(controller) { + controller.enqueue(new Uint8Array([1, 2, 3])); + controller.enqueue(new Uint8Array([4, 5, 6])); + controller.close(); + }, + }); + fetch("https://example.com", { body: byteStream }); +} + +{ + async function notGenerator() { + return "not a generator"; + } + // @ts-expect-error - Invalid async without generator + fetch("https://example.com", { body: notGenerator() }); +} + +{ + const invalidIterable = { + notAnIterator() { + return "invalid"; + }, + }; + // @ts-expect-error - Invalid object without proper iterator + fetch("https://example.com", { body: invalidIterable }); +} + +if (typeof process !== "undefined") { + // @ts-expect-error - Node.js specific invalid types + fetch("https://example.com", { body: process }); +} + +{ + // @ts-expect-error - Invalid number array (not typed) + fetch("https://example.com", { body: [1, 2, 3, 4] }); +} + +{ + // @ts-expect-error - Invalid nested structure + fetch("https://example.com", { body: { nested: { object: { structure: "invalid" } } } }); +} + +{ + // @ts-expect-error - NaN + fetch("https://example.com", { body: NaN }); +} + +{ + // @ts-expect-error - Infinity + fetch("https://example.com", { body: Infinity }); +} + +{ + // @ts-expect-error - -Infinity + fetch("https://example.com", { body: -Infinity }); +} diff --git a/test/integration/bun-types/fixture/index.ts b/test/integration/bun-types/fixture/index.ts index 5a1aeb28a2..a178c91a4b 100644 --- a/test/integration/bun-types/fixture/index.ts +++ b/test/integration/bun-types/fixture/index.ts @@ -181,7 +181,7 @@ for await (const chunk of Bun.stdin.stream()) { // this converts it to text (assumes ASCII encoding) const chunkText = Buffer.from(chunk).toString(); console.log(`Chunk: ${chunkText}`); - expectType(chunk).is(); + expectType(chunk).is>(); expectType(chunkText).is(); } diff --git a/test/integration/bun-types/fixture/serve-types.test.ts b/test/integration/bun-types/fixture/serve-types.test.ts index 3cf1aad375..408081cb31 100644 --- a/test/integration/bun-types/fixture/serve-types.test.ts +++ b/test/integration/bun-types/fixture/serve-types.test.ts @@ -225,7 +225,6 @@ test( test( "basic unix socket + websocket + upgrade", - // @ts-expect-error - TODO Fix this { unix: `${tmpdirSync()}/bun.sock`, fetch(req, server) { @@ -246,7 +245,6 @@ test( test( "basic unix socket + websocket + upgrade + tls", - // @ts-expect-error - TODO Fix this { unix: `${tmpdirSync()}/bun.sock`, fetch(req, server) { @@ -286,7 +284,6 @@ test( test( "basic unix socket + upgrade + cheap request to check upgrade", - // @ts-expect-error - TODO Fix this { unix: `${tmpdirSync()}/bun.sock`, fetch(req, server) { @@ -507,10 +504,11 @@ test("basic websocket upgrade and ws publish/subscribe to topics", { test( "port with unix socket (is a type error)", - { - unix: `${tmpdirSync()}/bun.sock`, - // @ts-expect-error - port: 0, + // This prettier-ignore exists because between TypeScript 5.8 and 5.9, the location of the error message changed, so + // to satisfy both we can just keep what would have been the two erroring lines on the same line + // prettier-ignore + // @ts-expect-error + { unix: `${tmpdirSync()}/bun.sock`, port: 0, fetch() { return new Response(); }, @@ -526,10 +524,10 @@ test( test( "port with unix socket with websocket + upgrade (is a type error)", - { - unix: `${tmpdirSync()}/bun.sock`, - // @ts-expect-error - port: 0, + // Prettier ignore exists for same reason as above + // prettier-ignore + // @ts-expect-error + { unix: `${tmpdirSync()}/bun.sock`, port: 0, fetch(req, server) { server.upgrade(req); if (Math.random() > 0.5) return undefined; diff --git a/test/integration/bun-types/fixture/spawn.ts b/test/integration/bun-types/fixture/spawn.ts index 1b2fc7b9a5..40fca022ad 100644 --- a/test/integration/bun-types/fixture/spawn.ts +++ b/test/integration/bun-types/fixture/spawn.ts @@ -49,7 +49,7 @@ function depromise(_promise: Promise): T { tsd.expectType(proc.pid).is(); - tsd.expectType(proc.stdout).is>(); + tsd.expectType(proc.stdout).is>>(); tsd.expectType(proc.stderr).is(); tsd.expectType(proc.stdin).is(); } @@ -74,8 +74,8 @@ function depromise(_promise: Promise): T { tsd.expectType(proc.stdio[3]).is(); tsd.expectType(proc.stdin).is(); - tsd.expectType(proc.stdout).is>(); - tsd.expectType(proc.stderr).is>(); + tsd.expectType(proc.stdout).is>>(); + tsd.expectType(proc.stderr).is>>(); } { diff --git a/test/integration/bun-types/fixture/sqlite.ts b/test/integration/bun-types/fixture/sqlite.ts index 4219dfcb7d..2aa2598f84 100644 --- a/test/integration/bun-types/fixture/sqlite.ts +++ b/test/integration/bun-types/fixture/sqlite.ts @@ -34,3 +34,19 @@ const query3 = db.prepare< >("select name, dob from users where id = $id"); const allResults3 = query3.all({ $id: "asdf" }); expectType>(allResults3); + +db.exec("CREATE TABLE cats (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, age INTEGER)"); +const insert = db.prepare("INSERT INTO cats (name, age) VALUES ($name, $age)"); +const insertManyCats = db.transaction((cats: Array<{ $name: string; $age: number }>) => { + for (const cat of cats) insert.run(cat); +}); +insertManyCats([ + { + $name: "Joey", + $age: 2, + }, + { $name: "Sally", $age: 4 }, + { $name: "Junior", $age: 1 }, + // @ts-expect-error - Should fail + { fail: true }, +]); diff --git a/test/integration/bun-types/fixture/streams.ts b/test/integration/bun-types/fixture/streams.ts index c725f953dc..ad484143db 100644 --- a/test/integration/bun-types/fixture/streams.ts +++ b/test/integration/bun-types/fixture/streams.ts @@ -42,10 +42,19 @@ for await (const chunk of uint8Transform.readable) { declare const stream: ReadableStream; expectType(stream.json()).is>(); -expectType(stream.bytes()).is>(); +expectType(stream.bytes()).is>>(); expectType(stream.text()).is>(); expectType(stream.blob()).is>(); +import { ReadableStream as NodeStreamReadableStream } from "node:stream/web"; + +declare const node_stream: NodeStreamReadableStream; + +expectType(node_stream.json()).is>(); +expectType(node_stream.bytes()).is>>(); +expectType(node_stream.text()).is>(); +expectType(node_stream.blob()).is>(); + Bun.file("./foo.csv").stream().pipeThrough(new TextDecoderStream()).pipeThrough(new TextEncoderStream()); Bun.file("./foo.csv") diff --git a/test/integration/bun-types/fixture/test.ts b/test/integration/bun-types/fixture/test.ts index 388d3705ee..dd915c6702 100644 --- a/test/integration/bun-types/fixture/test.ts +++ b/test/integration/bun-types/fixture/test.ts @@ -1,4 +1,17 @@ -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, jest, type Mock, spyOn, test } from "bun:test"; +import { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + expectTypeOf, + jest, + mock, + type Mock, + spyOn, + test, +} from "bun:test"; import { expectType } from "./utilities"; const hooks = [beforeAll, beforeEach, afterAll, afterEach]; @@ -144,3 +157,12 @@ expectType(spy.mock.calls).is<[message?: any, ...optionalParams: any[]][]>(); jest.spyOn(console, "log"); jest.fn(() => 123 as const); + +test("expectTypeOf basic type checks", () => { + expectTypeOf({ name: "test" }).toMatchObjectType<{ name: string }>(); + + // @ts-expect-error + expectTypeOf({ name: 123 }).toMatchObjectType<{ name: string }>(); +}); + +mock.clearAllMocks(); diff --git a/test/internal/ban-limits.json b/test/internal/ban-limits.json index 7fdd86cd88..9671650d8f 100644 --- a/test/internal/ban-limits.json +++ b/test/internal/ban-limits.json @@ -3,11 +3,11 @@ " == undefined": 0, "!= alloc.ptr": 0, "!= allocator.ptr": 0, - ".arguments_old(": 280, + ".arguments_old(": 279, ".stdDir()": 40, ".stdFile()": 18, "// autofix": 168, - ": [a-zA-Z0-9_\\.\\*\\?\\[\\]\\(\\)]+ = undefined,": 230, + ": [a-zA-Z0-9_\\.\\*\\?\\[\\]\\(\\)]+ = undefined,": 229, "== alloc.ptr": 0, "== allocator.ptr": 0, "@import(\"bun\").": 0, @@ -18,7 +18,7 @@ "allocator.ptr ==": 0, "global.hasException": 28, "globalObject.hasException": 42, - "globalThis.hasException": 134, + "globalThis.hasException": 133, "std.StringArrayHashMap(": 1, "std.StringArrayHashMapUnmanaged(": 12, "std.StringHashMap(": 0, @@ -30,7 +30,7 @@ "std.enums.tagName(": 2, "std.fs.Dir": 170, "std.fs.File": 62, - "std.fs.cwd": 103, + "std.fs.cwd": 104, "std.log": 1, "std.mem.indexOfAny(u8": 0, "std.unicode": 30, diff --git a/test/js/bun/http/body-leak-test-fixture.ts b/test/js/bun/http/body-leak-test-fixture.ts index 7c50ad8848..a8713fa094 100644 --- a/test/js/bun/http/body-leak-test-fixture.ts +++ b/test/js/bun/http/body-leak-test-fixture.ts @@ -39,9 +39,7 @@ const server = Bun.serve({ } } else if (url.endsWith("/incomplete-streaming")) { const reader = req.body?.getReader(); - if (!reader) { - reader?.read(); - } + await reader?.read(); } else if (url.endsWith("/streaming-echo")) { return new Response(req.body, { headers: { diff --git a/test/js/bun/http/serve-if-none-match.test.ts b/test/js/bun/http/serve-if-none-match.test.ts new file mode 100644 index 0000000000..1362435aa2 --- /dev/null +++ b/test/js/bun/http/serve-if-none-match.test.ts @@ -0,0 +1,268 @@ +import { afterAll, beforeAll, describe, expect, it } from "bun:test"; + +describe("If-None-Match Support", () => { + let server: Server; + + const testContent = "Hello, World!"; + const routes = { + "/basic": new Response(testContent, { + headers: { + "Content-Type": "text/plain", + }, + }), + "/with-etag": new Response("Custom content", { + headers: { + "Content-Type": "text/plain", + "ETag": '"custom-etag"', + }, + }), + "/weak-etag": new Response("Weak content", { + headers: { + "Content-Type": "text/plain", + "ETag": 'W/"weak-etag"', + }, + }), + }; + + beforeAll(async () => { + server = Bun.serve({ + static: routes, + port: 0, + fetch: () => new Response("Not Found", { status: 404 }), + }); + server.unref(); + }); + + afterAll(() => { + server.stop(true); + }); + + describe("ETag Generation", () => { + it("should automatically generate ETag for static responses", async () => { + const res = await fetch(`${server.url}basic`); + expect(res.status).toBe(200); + expect(res.headers.get("ETag")).toBeDefined(); + expect(res.headers.get("ETag")).toMatch(/^"[a-f0-9]+"$/); + expect(await res.text()).toBe(testContent); + }); + + it("should preserve existing ETag headers", async () => { + const res = await fetch(`${server.url}with-etag`); + expect(res.status).toBe(200); + expect(res.headers.get("ETag")).toBe('"custom-etag"'); + expect(await res.text()).toBe("Custom content"); + }); + + it("should preserve weak ETag headers", async () => { + const res = await fetch(`${server.url}weak-etag`); + expect(res.status).toBe(200); + expect(res.headers.get("ETag")).toBe('W/"weak-etag"'); + expect(await res.text()).toBe("Weak content"); + }); + }); + + describe("If-None-Match Evaluation", () => { + it("should return 304 when If-None-Match matches ETag", async () => { + // First request to get the ETag + const initialRes = await fetch(`${server.url}basic`); + const etag = initialRes.headers.get("ETag"); + expect(etag).toBeDefined(); + + // Second request with If-None-Match + const res = await fetch(`${server.url}basic`, { + headers: { + "If-None-Match": etag!, + }, + }); + + expect(res.status).toBe(304); + expect(res.headers.get("ETag")).toBe(etag); + expect(await res.text()).toBe(""); + }); + + it("should return 304 when If-None-Match matches custom ETag", async () => { + const res = await fetch(`${server.url}with-etag`, { + headers: { + "If-None-Match": '"custom-etag"', + }, + }); + + expect(res.status).toBe(304); + expect(res.headers.get("ETag")).toBe('"custom-etag"'); + expect(await res.text()).toBe(""); + }); + + it("should return 304 for weak ETag comparison", async () => { + const res = await fetch(`${server.url}weak-etag`, { + headers: { + "If-None-Match": 'W/"weak-etag"', + }, + }); + + expect(res.status).toBe(304); + expect(res.headers.get("ETag")).toBe('W/"weak-etag"'); + expect(await res.text()).toBe(""); + }); + + it("should return 304 when comparing strong vs weak ETags", async () => { + const res = await fetch(`${server.url}weak-etag`, { + headers: { + "If-None-Match": '"weak-etag"', // Strong comparison with weak ETag + }, + }); + + expect(res.status).toBe(304); + expect(res.headers.get("ETag")).toBe('W/"weak-etag"'); + expect(await res.text()).toBe(""); + }); + + it("should return 304 for '*' wildcard", async () => { + const res = await fetch(`${server.url}basic`, { + headers: { + "If-None-Match": "*", + }, + }); + + expect(res.status).toBe(304); + expect(await res.text()).toBe(""); + }); + + it("should handle multiple ETags in If-None-Match", async () => { + const initialRes = await fetch(`${server.url}basic`); + const etag = initialRes.headers.get("ETag"); + + const res = await fetch(`${server.url}basic`, { + headers: { + "If-None-Match": `"non-matching-etag", ${etag}, "another-etag"`, + }, + }); + + expect(res.status).toBe(304); + expect(await res.text()).toBe(""); + }); + + it("should return 200 when If-None-Match does not match", async () => { + const res = await fetch(`${server.url}basic`, { + headers: { + "If-None-Match": '"non-matching-etag"', + }, + }); + + expect(res.status).toBe(200); + expect(await res.text()).toBe(testContent); + }); + + it("should handle malformed If-None-Match headers gracefully", async () => { + const res = await fetch(`${server.url}basic`, { + headers: { + "If-None-Match": "malformed-etag-without-quotes", + }, + }); + + expect(res.status).toBe(200); + expect(await res.text()).toBe(testContent); + }); + + it("should handle whitespace in If-None-Match", async () => { + const initialRes = await fetch(`${server.url}basic`); + const etag = initialRes.headers.get("ETag"); + + const res = await fetch(`${server.url}basic`, { + headers: { + "If-None-Match": ` ${etag} `, + }, + }); + + expect(res.status).toBe(304); + expect(await res.text()).toBe(""); + }); + }); + + describe("HEAD Requests", () => { + it("should support If-None-Match with HEAD requests", async () => { + const initialRes = await fetch(`${server.url}basic`, { method: "HEAD" }); + const etag = initialRes.headers.get("ETag"); + expect(etag).toBeDefined(); + + const res = await fetch(`${server.url}basic`, { + method: "HEAD", + headers: { + "If-None-Match": etag!, + }, + }); + + expect(res.status).toBe(304); + expect(res.headers.get("ETag")).toBe(etag); + expect(await res.text()).toBe(""); + }); + + it("should return 200 for HEAD when If-None-Match does not match", async () => { + const res = await fetch(`${server.url}basic`, { + method: "HEAD", + headers: { + "If-None-Match": '"non-matching-etag"', + }, + }); + + expect(res.status).toBe(200); + expect(res.headers.get("Content-Length")).toBe(testContent.length.toString()); + expect(await res.text()).toBe(""); + }); + }); + + describe("Non-200 Status Codes", () => { + it("should not apply If-None-Match to redirects", async () => { + const redirectRoutes = { + "/redirect": Response.redirect("/basic", 302), + }; + + const redirectServer = Bun.serve({ + static: redirectRoutes, + port: 0, + fetch: () => new Response("Not Found", { status: 404 }), + }); + + try { + const res = await fetch(`${redirectServer.url}redirect`, { + redirect: "manual", + headers: { + "If-None-Match": "*", + }, + }); + + expect(res.status).toBe(302); + expect(res.headers.get("Location")).toBe("/basic"); + } finally { + redirectServer.stop(true); + } + }); + }); + + describe("Other HTTP Methods", () => { + it("should not apply If-None-Match to POST requests", async () => { + const res = await fetch(`${server.url}basic`, { + method: "POST", + headers: { + "If-None-Match": "*", + }, + }); + + // POST requests to static routes return the content normally (no If-None-Match applied) + expect(res.status).toBe(200); + expect(await res.text()).toBe(testContent); + }); + + it("should not apply If-None-Match to PUT requests", async () => { + const res = await fetch(`${server.url}basic`, { + method: "PUT", + headers: { + "If-None-Match": "*", + }, + }); + + // PUT requests to static routes return the content normally (no If-None-Match applied) + expect(res.status).toBe(200); + expect(await res.text()).toBe(testContent); + }); + }); +}); diff --git a/test/js/bun/perf/static-initializers.test.ts b/test/js/bun/perf/static-initializers.test.ts index 1977f495f6..7648aa8862 100644 --- a/test/js/bun/perf/static-initializers.test.ts +++ b/test/js/bun/perf/static-initializers.test.ts @@ -64,6 +64,6 @@ describe("static initializers", () => { expect( bunInitializers.length, `Do not add static initializers to Bun. Static initializers are called when Bun starts up, regardless of whether you use the variables or not. This makes Bun slower.`, - ).toBe(process.arch == "arm64" ? 1 : 2); + ).toBe(process.arch == "arm64" ? 3 : 4); }); }); diff --git a/test/js/bun/resolve/resolve-error.test.ts b/test/js/bun/resolve/resolve-error.test.ts index 513269e67f..834cc7ff7b 100644 --- a/test/js/bun/resolve/resolve-error.test.ts +++ b/test/js/bun/resolve/resolve-error.test.ts @@ -52,4 +52,11 @@ describe("ResolveMessage", () => { await import("data:Hello%2C%20World!"); }).toThrow("Cannot resolve invalid data URL"); }); + + it("doesn't crash", async () => { + expect(async () => { + // @ts-ignore + await import(":://filesystem"); + }).toThrow("Cannot find module"); + }); }); diff --git a/test/js/bun/test/expect-toHaveReturnedWith.test.js b/test/js/bun/test/expect-toHaveReturnedWith.test.js new file mode 100644 index 0000000000..50a71069a0 --- /dev/null +++ b/test/js/bun/test/expect-toHaveReturnedWith.test.js @@ -0,0 +1,195 @@ +import { expect, jest, test } from "bun:test"; + +test("toHaveReturnedWith basic functionality", () => { + const mockFn = jest.fn(() => "La Croix"); + + // Function hasn't been called yet + expect(() => { + expect(mockFn).toHaveReturnedWith("La Croix"); + }).toThrow(); + + // Call the function + mockFn(); + + // Should pass - the function returned 'La Croix' + expect(mockFn).toHaveReturnedWith("La Croix"); + + // Should fail - the function didn't return this value + expect(() => { + expect(mockFn).toHaveReturnedWith("Pepsi"); + }).toThrow(); +}); + +test("toHaveReturnedWith with multiple returns", () => { + const mockFn = jest.fn(); + + mockFn.mockReturnValueOnce("first"); + mockFn.mockReturnValueOnce("second"); + mockFn.mockReturnValueOnce("third"); + + // Call the function multiple times + mockFn(); + mockFn(); + mockFn(); + + // Should pass for all returned values + expect(mockFn).toHaveReturnedWith("first"); + expect(mockFn).toHaveReturnedWith("second"); + expect(mockFn).toHaveReturnedWith("third"); + + // Should fail for values not returned + expect(() => { + expect(mockFn).toHaveReturnedWith("fourth"); + }).toThrow(); +}); + +test("toHaveReturnedWith with objects", () => { + const obj = { name: "La Croix" }; + const mockFn = jest.fn(() => obj); + + mockFn(); + + // Should pass with deep equality + expect(mockFn).toHaveReturnedWith({ name: "La Croix" }); + + // Should also pass with same object reference + expect(mockFn).toHaveReturnedWith(obj); + + // Should fail with different object + expect(() => { + expect(mockFn).toHaveReturnedWith({ name: "Pepsi" }); + }).toThrow(); +}); + +test("toHaveReturnedWith with arrays", () => { + const mockFn = jest.fn(() => [1, 2, 3]); + + mockFn(); + + // Should pass with deep equality + expect(mockFn).toHaveReturnedWith([1, 2, 3]); + + // Should fail with different array + expect(() => { + expect(mockFn).toHaveReturnedWith([1, 2, 4]); + }).toThrow(); +}); + +test("toHaveReturnedWith with undefined and null", () => { + const mockFn = jest.fn(); + + mockFn(); // returns undefined by default + mockFn.mockReturnValueOnce(null); + mockFn(); + + expect(mockFn).toHaveReturnedWith(undefined); + expect(mockFn).toHaveReturnedWith(null); +}); + +test("toHaveReturnedWith with thrown errors", () => { + const mockFn = jest.fn(); + + mockFn.mockReturnValueOnce("success"); + mockFn(); // returns 'success' + + // Mock a throw for the next call + mockFn.mockImplementationOnce(() => { + throw new Error("Failed"); + }); + + expect(() => mockFn()).toThrow("Failed"); + + // Should still pass for the successful return + expect(mockFn).toHaveReturnedWith("success"); + + // But not for values that were never returned + expect(() => { + expect(mockFn).toHaveReturnedWith("Failed"); + }).toThrow(); +}); + +test("toHaveReturnedWith with .not modifier", () => { + const mockFn = jest.fn(() => "La Croix"); + + mockFn(); + + // Should pass - the function didn't return 'Pepsi' + expect(mockFn).not.toHaveReturnedWith("Pepsi"); + + // Should fail - the function did return 'La Croix' + expect(() => { + expect(mockFn).not.toHaveReturnedWith("La Croix"); + }).toThrow(); +}); + +test("drink returns La Croix example from Jest docs", () => { + const beverage = { name: "La Croix" }; + const drink = jest.fn(beverage => beverage.name); + + drink(beverage); + + expect(drink).toHaveReturnedWith("La Croix"); +}); + +test("toHaveReturnedWith with primitive values", () => { + const mockFn = jest.fn(); + + mockFn.mockReturnValueOnce(42); + mockFn.mockReturnValueOnce(true); + mockFn.mockReturnValueOnce("hello"); + mockFn.mockReturnValueOnce(3.14); + + mockFn(); + mockFn(); + mockFn(); + mockFn(); + + expect(mockFn).toHaveReturnedWith(42); + expect(mockFn).toHaveReturnedWith(true); + expect(mockFn).toHaveReturnedWith("hello"); + expect(mockFn).toHaveReturnedWith(3.14); + + // Should fail for values not returned + expect(() => { + expect(mockFn).toHaveReturnedWith(false); + }).toThrow(); + + expect(() => { + expect(mockFn).toHaveReturnedWith(43); + }).toThrow(); +}); + +test("toHaveReturnedWith should require a mock function", () => { + const notAMock = () => "La Croix"; + + expect(() => { + expect(notAMock).toHaveReturnedWith("La Croix"); + }).toThrow("Expected value must be a mock function"); +}); + +test("toHaveReturnedWith should require an argument", () => { + const mockFn = jest.fn(() => "La Croix"); + mockFn(); + + expect(() => { + // @ts-expect-error - testing invalid usage + expect(mockFn).toHaveReturnedWith(); + }).toThrow(); +}); + +test("toHaveReturnedWith with promises using async/await", async () => { + const mockFn = jest.fn(async () => "async result"); + + await mockFn(); + + expect(mockFn).toHaveReturnedWith(expect.any(Promise)); +}); + +test("toHaveReturnedWith checks the resolved value, not the promise", async () => { + const mockFn = jest.fn(async () => "async result"); + + await mockFn(); + + // The mock tracks the promise as the return value, not the resolved value + expect(mockFn).not.toHaveReturnedWith("async result"); +}); diff --git a/test/js/bun/test/expect-type-doctest.test.ts b/test/js/bun/test/expect-type-doctest.test.ts new file mode 100644 index 0000000000..7b9fd77911 --- /dev/null +++ b/test/js/bun/test/expect-type-doctest.test.ts @@ -0,0 +1,24 @@ +import { expectTypeOf } from "bun:test"; + +// Basic type assertions +expectTypeOf().toEqualTypeOf(); +expectTypeOf(123).toBeNumber(); +expectTypeOf("hello").toBeString(); + +// Object type matching +expectTypeOf({ a: 1, b: "hello" }).toMatchObjectType<{ a: number }>(); + +// Function types +function greet(name: string): string { + return `Hello ${name}`; +} + +expectTypeOf(greet).toBeFunction(); +expectTypeOf(greet).parameters.toEqualTypeOf<[string]>(); +expectTypeOf(greet).returns.toEqualTypeOf(); + +// Array types +expectTypeOf([1, 2, 3]).items.toBeNumber(); + +// Promise types +expectTypeOf(Promise.resolve(42)).resolves.toBeNumber(); diff --git a/test/js/bun/test/expect-type-global.test.ts b/test/js/bun/test/expect-type-global.test.ts new file mode 100644 index 0000000000..497a8c6952 --- /dev/null +++ b/test/js/bun/test/expect-type-global.test.ts @@ -0,0 +1,6 @@ +test("types", () => { + expectTypeOf({ a: 1 }).toMatchObjectType<{ a: number }>(); + // @ts-expect-error + expectTypeOf({ a: 1 }).toMatchObjectType<{ a: 1 }>(); + expectTypeOf({ a: 1 as const }).toMatchObjectType<{ a: 1 }>(); +}); diff --git a/test/js/bun/test/expect-type.test.ts b/test/js/bun/test/expect-type.test.ts new file mode 100644 index 0000000000..f155e0b238 --- /dev/null +++ b/test/js/bun/test/expect-type.test.ts @@ -0,0 +1,8 @@ +import { expectTypeOf, test } from "bun:test"; + +test("types", () => { + expectTypeOf({ a: 1 }).toMatchObjectType<{ a: number }>(); + // @ts-expect-error + expectTypeOf({ a: 1 }).toMatchObjectType<{ a: 1 }>(); + expectTypeOf({ a: 1 as const }).toMatchObjectType<{ a: 1 }>(); +}); diff --git a/test/js/bun/test/expect/toHaveReturnedWith.test.ts b/test/js/bun/test/expect/toHaveReturnedWith.test.ts new file mode 100644 index 0000000000..b9563a1a6f --- /dev/null +++ b/test/js/bun/test/expect/toHaveReturnedWith.test.ts @@ -0,0 +1,503 @@ +import { beforeEach, describe, expect, jest, test } from "bun:test"; + +// Example functions for testing toHaveReturnedWith +export function add(a: number, b: number): number { + return a + b; +} + +export function multiply(a: number, b: number): number { + return a * b; +} + +export function greet(name: string): string { + return `Hello, ${name}!`; +} + +export function getRandomNumber(): number { + return Math.floor(Math.random() * 100); +} + +export function createUser(name: string, age: number): { name: string; age: number } { + return { name, age }; +} + +console.log("Hello via Bun!"); + +describe("toHaveReturnedWith Examples", () => { + let mockAdd: ReturnType; + let mockMultiply: ReturnType; + let mockGreet: ReturnType; + let mockGetRandomNumber: ReturnType; + let mockCreateUser: ReturnType; + + beforeEach(() => { + // Reset all mocks before each test + mockAdd = jest.fn(add); + mockMultiply = jest.fn(multiply); + mockGreet = jest.fn(greet); + mockGetRandomNumber = jest.fn(getRandomNumber); + mockCreateUser = jest.fn(createUser); + }); + + describe("Success Cases - toHaveReturnedWith", () => { + test("should pass when function returns expected number", () => { + const result = mockAdd(2, 3); + expect(mockAdd).toHaveReturnedWith(5); + expect(result).toBe(5); + }); + + test("should pass when function returns expected string", () => { + const result = mockGreet("Alice"); + expect(mockGreet).toHaveReturnedWith("Hello, Alice!"); + expect(result).toBe("Hello, Alice!"); + }); + + test("should pass when function returns expected object", () => { + const result = mockCreateUser("Bob", 30); + expect(mockCreateUser).toHaveReturnedWith({ name: "Bob", age: 30 }); + expect(result).toEqual({ name: "Bob", age: 30 }); + }); + + test("should pass when function returns expected value after multiple calls", () => { + mockMultiply(2, 3); // Returns 6 + mockMultiply(4, 5); // Returns 20 + mockMultiply(1, 1); // Returns 1 + + expect(mockMultiply).toHaveReturnedWith(6); + expect(mockMultiply).toHaveReturnedWith(20); + expect(mockMultiply).toHaveReturnedWith(1); + }); + + test("should pass with exact array match", () => { + const mockArrayFunction = jest.fn(() => [1, 2, 3]); + const result = mockArrayFunction(); + expect(mockArrayFunction).toHaveReturnedWith([1, 2, 3]); + expect(result).toEqual([1, 2, 3]); + }); + + test("should pass with null return value", () => { + const mockNullFunction = jest.fn(() => null); + const result = mockNullFunction(); + expect(mockNullFunction).toHaveReturnedWith(null); + expect(result).toBeNull(); + }); + + test("should pass with undefined return value", () => { + const mockUndefinedFunction = jest.fn(() => undefined); + const result = mockUndefinedFunction(); + expect(mockUndefinedFunction).toHaveReturnedWith(undefined); + expect(result).toBeUndefined(); + }); + }); + + describe("Fail Cases - toHaveReturnedWith", () => { + test("should fail when function returns different number", () => { + const result = mockAdd(2, 3); + // This will fail because add(2, 3) returns 5, not 10 + expect(() => { + expect(mockAdd).toHaveReturnedWith(10); + }).toThrow(); + }); + + test("should fail when function returns different string", () => { + const result = mockGreet("Alice"); + // This will fail because greet("Alice") returns "Hello, Alice!", not "Hi, Alice!" + expect(() => { + expect(mockGreet).toHaveReturnedWith("Hi, Alice!"); + }).toThrow(); + }); + + test("should fail when function returns different object", () => { + const result = mockCreateUser("Bob", 30); + // This will fail because the returned object has different age + expect(() => { + expect(mockCreateUser).toHaveReturnedWith({ name: "Bob", age: 25 }); + }).toThrow(); + }); + + test("should fail when function was never called", () => { + // mockAdd was never called, so this will fail + expect(() => { + expect(mockAdd).toHaveReturnedWith(5); + }).toThrow(); + }); + + test("should fail when function returns different array", () => { + const mockArrayFunction = jest.fn(() => [1, 2, 3]); + const result = mockArrayFunction(); + // This will fail because the expected array is different + expect(() => { + expect(mockArrayFunction).toHaveReturnedWith([1, 2, 4]); + }).toThrow(); + }); + + test("should fail when expecting null but function returns value", () => { + const result = mockAdd(2, 3); + // This will fail because add returns 5, not null + expect(() => { + expect(mockAdd).toHaveReturnedWith(null); + }).toThrow(); + }); + + test("should fail when expecting value but function returns null", () => { + const mockNullFunction = jest.fn(() => null); + const result = mockNullFunction(); + // This will fail because function returns null, not 5 + expect(() => { + expect(mockNullFunction).toHaveReturnedWith(5); + }).toThrow(); + }); + }); + + describe("Edge Cases and Advanced Examples", () => { + test("should work with multiple return values in sequence", () => { + mockAdd(1, 1); // Returns 2 + mockAdd(2, 2); // Returns 4 + mockAdd(3, 3); // Returns 6 + + // All these should pass + expect(mockAdd).toHaveReturnedWith(2); + expect(mockAdd).toHaveReturnedWith(4); + expect(mockAdd).toHaveReturnedWith(6); + }); + + test("should work with complex objects", () => { + const mockComplexFunction = jest.fn(() => ({ + id: 1, + name: "Test", + metadata: { + createdAt: "2024-01-01", + tags: ["tag1", "tag2"], + }, + })); + + const result = mockComplexFunction(); + expect(mockComplexFunction).toHaveReturnedWith({ + id: 1, + name: "Test", + metadata: { + createdAt: "2024-01-01", + tags: ["tag1", "tag2"], + }, + }); + }); + + test("should fail with partial object match", () => { + const mockComplexFunction = jest.fn(() => ({ + id: 1, + name: "Test", + metadata: { + createdAt: "2024-01-01", + tags: ["tag1", "tag2"], + }, + })); + + const result = mockComplexFunction(); + // This will fail because the expected object is missing the metadata property + expect(() => { + expect(mockComplexFunction).toHaveReturnedWith({ + id: 1, + name: "Test", + }); + }).toThrow(); + }); + + test("should work with functions that return functions", () => { + const mockFunctionFactory = jest.fn(() => (x: number) => x * 2); + const result = mockFunctionFactory(); + + expect(mockFunctionFactory).toHaveReturnedWith(expect.any(Function)); + expect(result(5)).toBe(10); + }); + }); + + describe("Common Mistakes and How to Avoid Them", () => { + test("mistake: checking return value instead of using toHaveReturnedWith", () => { + const result = mockAdd(2, 3); + + // ❌ Wrong way - checking the result directly + expect(result).toBe(5); + + // ✅ Correct way - checking that the mock returned the expected value + expect(mockAdd).toHaveReturnedWith(5); + }); + + test("mistake: not calling the function before checking toHaveReturnedWith", () => { + // ❌ This will fail because the function was never called + expect(() => { + expect(mockAdd).toHaveReturnedWith(5); + }).toThrow(); + + // ✅ Correct way - call the function first + mockAdd(2, 3); + expect(mockAdd).toHaveReturnedWith(5); + }); + + test("mistake: using toHaveReturnedWith on non-mock functions", () => { + // ❌ This won't work because add is not a mock + const result = add(2, 3); + expect(() => { + expect(add).toHaveReturnedWith(5); + }).toThrow(); + + // ✅ Correct way - use the mock + const mockResult = mockAdd(2, 3); + expect(mockAdd).toHaveReturnedWith(5); + }); + }); +}); + +describe("toHaveLastReturnedWith Examples", () => { + let mockAdd: ReturnType; + let mockMultiply: ReturnType; + let mockGreet: ReturnType; + let mockGetRandomNumber: ReturnType; + let mockCreateUser: ReturnType; + let mockDrink: ReturnType; + + beforeEach(() => { + // Reset all mocks before each test + mockAdd = jest.fn(add); + mockMultiply = jest.fn(multiply); + mockGreet = jest.fn(greet); + mockGetRandomNumber = jest.fn(getRandomNumber); + mockCreateUser = jest.fn(createUser); + mockDrink = jest.fn((beverage: { name: string }) => beverage.name); + }); + + describe("Success Cases - toHaveLastReturnedWith", () => { + test("should pass when last call returns expected value", () => { + mockAdd(1, 1); // Returns 2 + mockAdd(2, 3); // Returns 5 + mockAdd(3, 4); // Returns 7 - last call + + expect(mockAdd).toHaveLastReturnedWith(7); + }); + + test("should pass when last call returns expected string", () => { + mockGreet("Alice"); // Returns "Hello, Alice!" + mockGreet("Bob"); // Returns "Hello, Bob!" + mockGreet("Carol"); // Returns "Hello, Carol!" - last call + + expect(mockGreet).toHaveLastReturnedWith("Hello, Carol!"); + }); + + test("should pass when last call returns expected object", () => { + mockCreateUser("Alice", 25); + mockCreateUser("Bob", 30); + mockCreateUser("Carol", 35); // Last call + + expect(mockCreateUser).toHaveLastReturnedWith({ name: "Carol", age: 35 }); + }); + + test("drink returns La Croix (Orange) last", () => { + const beverage1 = { name: "La Croix (Lemon)" }; + const beverage2 = { name: "La Croix (Orange)" }; + + mockDrink(beverage1); + mockDrink(beverage2); + + expect(mockDrink).toHaveLastReturnedWith("La Croix (Orange)"); + }); + + test("should pass with single call", () => { + mockMultiply(5, 6); // Only one call, returns 30 + + expect(mockMultiply).toHaveLastReturnedWith(30); + }); + + test("should pass with null as last return value", () => { + const mockNullFunction = jest.fn().mockReturnValueOnce(5).mockReturnValueOnce("test").mockReturnValueOnce(null); + + mockNullFunction(); + mockNullFunction(); + mockNullFunction(); // Returns null + + expect(mockNullFunction).toHaveLastReturnedWith(null); + }); + + test("should pass with undefined as last return value", () => { + const mockUndefinedFunction = jest.fn().mockReturnValueOnce(10).mockReturnValueOnce(undefined); + + mockUndefinedFunction(); + mockUndefinedFunction(); // Returns undefined + + expect(mockUndefinedFunction).toHaveLastReturnedWith(undefined); + }); + + test("should pass with array as last return value", () => { + const mockArrayFunction = jest.fn(); + mockArrayFunction.mockReturnValueOnce([1, 2]); + mockArrayFunction.mockReturnValueOnce([3, 4, 5]); + + mockArrayFunction(); + mockArrayFunction(); // Returns [3, 4, 5] + + expect(mockArrayFunction).toHaveLastReturnedWith([3, 4, 5]); + }); + }); + + describe("Fail Cases - toHaveLastReturnedWith", () => { + test("should fail when last call returns different value", () => { + mockAdd(1, 1); // Returns 2 + mockAdd(2, 3); // Returns 5 + mockAdd(3, 4); // Returns 7 - last call + + // This will fail because last call returned 7, not 5 + expect(() => { + expect(mockAdd).toHaveLastReturnedWith(5); + }).toThrow(); + }); + + test("should fail when checking non-last return value", () => { + mockGreet("Alice"); // Returns "Hello, Alice!" + mockGreet("Bob"); // Returns "Hello, Bob!" - last call + + // This will fail because last call returned "Hello, Bob!", not "Hello, Alice!" + expect(() => { + expect(mockGreet).toHaveLastReturnedWith("Hello, Alice!"); + }).toThrow(); + }); + + test("should fail when function was never called", () => { + // mockAdd was never called + expect(() => { + expect(mockAdd).toHaveLastReturnedWith(5); + }).toThrow(); + }); + + test("should fail when last call threw an error", () => { + const mockThrowFunction = jest + .fn() + .mockReturnValueOnce(5) + .mockImplementationOnce(() => { + throw new Error("Test error"); + }); + + mockThrowFunction(); // Returns 5 + + // Last call will throw + expect(() => { + mockThrowFunction(); + }).toThrow("Test error"); + + // This will fail because last call threw an error + expect(() => { + expect(mockThrowFunction).toHaveLastReturnedWith(5); + }).toThrow(); + }); + + test("should fail with wrong object in last call", () => { + mockCreateUser("Alice", 25); + mockCreateUser("Bob", 30); // Last call + + // This will fail because last call returned Bob, not Alice + expect(() => { + expect(mockCreateUser).toHaveLastReturnedWith({ name: "Alice", age: 25 }); + }).toThrow(); + }); + + test("should fail with wrong array in last call", () => { + const mockArrayFunction = jest.fn(); + mockArrayFunction.mockReturnValueOnce([1, 2]); + mockArrayFunction.mockReturnValueOnce([3, 4, 5]); + + mockArrayFunction(); + mockArrayFunction(); // Returns [3, 4, 5] + + // This will fail because last call returned [3, 4, 5], not [1, 2] + expect(() => { + expect(mockArrayFunction).toHaveLastReturnedWith([1, 2]); + }).toThrow(); + }); + }); + + describe("Edge Cases - toHaveLastReturnedWith", () => { + test("should work with functions returning functions", () => { + const mockFunctionFactory = jest.fn(); + const fn1 = (x: number) => x * 2; + const fn2 = (x: number) => x * 3; + + mockFunctionFactory.mockReturnValueOnce(fn1); + mockFunctionFactory.mockReturnValueOnce(fn2); + + mockFunctionFactory(); + const lastResult = mockFunctionFactory(); // Returns fn2 + + expect(mockFunctionFactory).toHaveLastReturnedWith(fn2); + expect(lastResult(5)).toBe(15); // 5 * 3 + }); + + test("should work with complex nested objects", () => { + const mockComplexFunction = jest.fn(); + const obj1 = { id: 1, data: { nested: { value: 10 } } }; + const obj2 = { id: 2, data: { nested: { value: 20 } } }; + + mockComplexFunction.mockReturnValueOnce(obj1); + mockComplexFunction.mockReturnValueOnce(obj2); + + mockComplexFunction(); + mockComplexFunction(); // Returns obj2 + + expect(mockComplexFunction).toHaveLastReturnedWith({ + id: 2, + data: { nested: { value: 20 } }, + }); + }); + + test("should distinguish between similar values in sequence", () => { + mockAdd(1, 1); // Returns 2 + mockAdd(1, 1); // Returns 2 + mockAdd(2, 0); // Returns 2 - last call + + // All calls return 2, but toHaveLastReturnedWith should still pass + expect(mockAdd).toHaveLastReturnedWith(2); + }); + + test("should work after many calls", () => { + // Make 100 calls + for (let i = 0; i < 100; i++) { + mockMultiply(i, 2); // Returns i * 2 + } + + // Last call was mockMultiply(99, 2) which returns 198 + expect(mockMultiply).toHaveLastReturnedWith(198); + }); + + test("should handle symbol return values", () => { + const sym1 = Symbol("first"); + const sym2 = Symbol("last"); + const mockSymbolFunction = jest.fn(); + + mockSymbolFunction.mockReturnValueOnce(sym1); + mockSymbolFunction.mockReturnValueOnce(sym2); + + mockSymbolFunction(); + mockSymbolFunction(); // Returns sym2 + + expect(mockSymbolFunction).toHaveLastReturnedWith(sym2); + }); + }); + + describe("Comparison with toHaveReturnedWith", () => { + test("toHaveReturnedWith checks any call, toHaveLastReturnedWith checks only last", () => { + mockAdd(1, 1); // Returns 2 + mockAdd(2, 3); // Returns 5 + mockAdd(3, 4); // Returns 7 - last call + + // toHaveReturnedWith passes for any return value + expect(mockAdd).toHaveReturnedWith(2); + expect(mockAdd).toHaveReturnedWith(5); + expect(mockAdd).toHaveReturnedWith(7); + + // toHaveLastReturnedWith only passes for the last return value + expect(mockAdd).toHaveLastReturnedWith(7); + expect(() => { + expect(mockAdd).toHaveLastReturnedWith(2); + }).toThrow(); + expect(() => { + expect(mockAdd).toHaveLastReturnedWith(5); + }).toThrow(); + }); + }); +}); diff --git a/test/js/bun/test/jest.d.ts b/test/js/bun/test/jest.d.ts index 2d21e87e05..700f8c9679 100644 --- a/test/js/bun/test/jest.d.ts +++ b/test/js/bun/test/jest.d.ts @@ -2,6 +2,7 @@ declare var jest: typeof import("bun:test").jest; declare var describe: typeof import("bun:test").describe; declare var test: typeof import("bun:test").test; declare var expect: typeof import("bun:test").expect; +declare var expectTypeOf: typeof import("bun:test").expectTypeOf; declare var it: typeof import("bun:test").it; declare var beforeEach: typeof import("bun:test").beforeEach; declare var afterEach: typeof import("bun:test").afterEach; diff --git a/test/js/bun/test/mock-fn.test.js b/test/js/bun/test/mock-fn.test.js index 4f813f7ffa..128f1fa110 100644 --- a/test/js/bun/test/mock-fn.test.js +++ b/test/js/bun/test/mock-fn.test.js @@ -164,10 +164,72 @@ describe("mock()", () => { try { expect(func2).toHaveReturned(); } catch (e) { - expect(e.message).toContain("Function threw an exception"); + expect(e.message.replaceAll(/\x1B\[[0-9;]*m/g, "")).toMatchInlineSnapshot(` + "expect(received).toHaveReturned(expected) + + Expected number of succesful returns: >= 1 + Received number of succesful returns: 0 + Received number of calls: 1 + " + `); } }); + test("toHaveNthReturnedWith", () => { + const fn = jest.fn(); + + // Test when function hasn't been called + expect(() => expect(fn).toHaveNthReturnedWith(1, "value")).toThrow(); + + // Call with different return values + fn.mockReturnValueOnce("first"); + fn.mockReturnValueOnce("second"); + fn.mockReturnValueOnce("third"); + + fn(); + fn(); + fn(); + + // Test positive cases + expect(fn).toHaveNthReturnedWith(1, "first"); + expect(fn).toHaveNthReturnedWith(2, "second"); + expect(fn).toHaveNthReturnedWith(3, "third"); + + // Test negative cases + expect(fn).not.toHaveNthReturnedWith(1, "wrong"); + expect(fn).not.toHaveNthReturnedWith(2, "wrong"); + expect(fn).not.toHaveNthReturnedWith(3, "wrong"); + + // Test out of bounds + expect(() => expect(fn).toHaveNthReturnedWith(4, "value")).toThrow(); + expect(() => expect(fn).toHaveNthReturnedWith(0, "value")).toThrow(); + expect(() => expect(fn).toHaveNthReturnedWith(-1, "value")).toThrow(); + + // Test with objects + const obj1 = { a: 1 }; + const obj2 = { b: 2 }; + fn.mockReturnValueOnce(obj1); + fn.mockReturnValueOnce(obj2); + + fn(); + fn(); + + expect(fn).toHaveNthReturnedWith(4, obj1); + expect(fn).toHaveNthReturnedWith(5, obj2); + + // Test with thrown errors + const error = new Error("test error"); + fn.mockImplementationOnce(() => { + throw error; + }); + + try { + fn(); + } catch (e) {} + + expect(() => expect(fn).toHaveNthReturnedWith(6, "value")).toThrow(); + }); + test("passes this value", () => { const fn = jest.fn(function hey() { "use strict"; @@ -599,6 +661,11 @@ describe("mock()", () => { expect(await expectRejects(fn())).toBe(44); expect(await expectRejects(fn())).toBe(42); }); + test("mockRejectedValue doesn't throw when never called", () => { + const fn = jest.fn().mockRejectedValue(new Error("Test error")); + expect(fn).toBeDefined(); + expect(typeof fn).toBe("function"); + }); test("withImplementation (sync)", () => { const fn = jest.fn(() => "1"); expect(fn()).toBe("1"); diff --git a/test/js/bun/test/spyMatchers.test.ts b/test/js/bun/test/spyMatchers.test.ts new file mode 100644 index 0000000000..a9e2ebb98b --- /dev/null +++ b/test/js/bun/test/spyMatchers.test.ts @@ -0,0 +1,1324 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + +MIT License + +Copyright (c) Meta Platforms, Inc. and affiliates. +Copyright Contributors to the Jest project. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +import { describe, expect, jest, expect as jestExpect, test } from "bun:test"; +import * as Immutable from "immutable"; +import type { FunctionLike } from "jest-mock"; + +jestExpect.extend({ + optionalFn(fn?: unknown) { + const pass = fn === undefined || typeof fn === "function"; + return { message: () => "expect either a function or undefined", pass }; + }, +}); + +// Given a Jest mock function, return a minimal mock of a spy. +const createSpy = (fn: jest.Mock): jest.Mock => { + const spy = function () {}; + + spy.calls = { + all() { + return fn.mock.calls.map(args => ({ args })); + }, + count() { + return fn.mock.calls.length; + }, + }; + + return spy as unknown as jest.Mock; +}; + +describe("toHaveBeenCalled", () => { + test("works only on spies or jest.fn", () => { + const fn = function fn() {}; + + expect(() => jestExpect(fn).toHaveBeenCalled()).toThrow(); + }); + + test("passes when called", () => { + const fn = jest.fn(); + fn("arg0", "arg1", "arg2"); + // jestExpect(createSpy(fn)).toHaveBeenCalled(); + jestExpect(fn).toHaveBeenCalled(); + expect(() => jestExpect(fn).not.toHaveBeenCalled()).toThrow(); + }); + + test(".not passes when called", () => { + const fn = jest.fn(); + // const spy = createSpy(fn); + + // jestExpect(spy).not.toHaveBeenCalled(); + jestExpect(fn).not.toHaveBeenCalled(); + // expect(() => jestExpect(spy).toHaveBeenCalled()).toThrow(); + expect(() => jestExpect(fn).toHaveBeenCalled()).toThrow(); + }); + + test("fails with any argument passed", () => { + const fn = jest.fn(); + + fn(); + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).toHaveBeenCalled(555), + ).toThrow(); + }); + + test(".not fails with any argument passed", () => { + const fn = jest.fn(); + + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).not.toHaveBeenCalled(555), + ).toThrow(); + }); + + test("includes the custom mock name in the error message", () => { + const fn = jest.fn().mockName("named-mock"); + + fn(); + jestExpect(fn).toHaveBeenCalled(); + expect(() => jestExpect(fn).not.toHaveBeenCalled()).toThrow(); + }); +}); + +describe("toHaveBeenCalledTimes", () => { + test(".not works only on spies or jest.fn", () => { + const fn = function fn() {}; + + expect(() => jestExpect(fn).not.toHaveBeenCalledTimes(2)).toThrow(); + }); + + test("only accepts a number argument", () => { + const fn = jest.fn(); + fn(); + jestExpect(fn).toHaveBeenCalledTimes(1); + + for (const value of [{}, [], true, "a", new Map(), () => {}]) { + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).toHaveBeenCalledTimes(value), + ).toThrow(); + } + }); + + test(".not only accepts a number argument", () => { + const fn = jest.fn(); + jestExpect(fn).not.toHaveBeenCalledTimes(1); + + for (const value of [{}, [], true, "a", new Map(), () => {}]) { + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).not.toHaveBeenCalledTimes(value), + ).toThrow(); + } + }); + + test("passes if function called equal to expected times", () => { + const fn = jest.fn(); + fn(); + fn(); + + // const spy = createSpy(fn); + // jestExpect(spy).toHaveBeenCalledTimes(2); + jestExpect(fn).toHaveBeenCalledTimes(2); + + // expect(() => jestExpect(spy).not.toHaveBeenCalledTimes(2)).toThrow(); + expect(() => jestExpect(fn).not.toHaveBeenCalledTimes(2)).toThrow(); + }); + + test(".not passes if function called more than expected times", () => { + const fn = jest.fn(); + fn(); + fn(); + fn(); + + // const spy = createSpy(fn); + // jestExpect(spy).toHaveBeenCalledTimes(3); + // jestExpect(spy).not.toHaveBeenCalledTimes(2); + + jestExpect(fn).toHaveBeenCalledTimes(3); + jestExpect(fn).not.toHaveBeenCalledTimes(2); + + expect(() => jestExpect(fn).toHaveBeenCalledTimes(2)).toThrow(); + }); + + test(".not passes if function called less than expected times", () => { + const fn = jest.fn(); + fn(); + + // const spy = createSpy(fn); + // jestExpect(spy).toHaveBeenCalledTimes(1); + // jestExpect(spy).not.toHaveBeenCalledTimes(2); + + jestExpect(fn).toHaveBeenCalledTimes(1); + jestExpect(fn).not.toHaveBeenCalledTimes(2); + + expect(() => jestExpect(fn).toHaveBeenCalledTimes(2)).toThrow(); + }); + + test("includes the custom mock name in the error message", () => { + const fn = jest.fn().mockName("named-mock"); + fn(); + + expect(() => jestExpect(fn).toHaveBeenCalledTimes(2)).toThrow(); + }); +}); + +describe.each(["toHaveBeenLastCalledWith", "toHaveBeenNthCalledWith", "toHaveBeenCalledWith"] as const)( + "%s", + calledWith => { + function isToHaveNth(calledWith: string): calledWith is "toHaveBeenNthCalledWith" { + return calledWith === "toHaveBeenNthCalledWith"; + } + + test("works only on spies or jest.fn", () => { + const fn = function fn() {}; + + if (isToHaveNth(calledWith)) { + expect(() => jestExpect(fn)[calledWith](3)).toThrow(); + } else { + expect(() => jestExpect(fn)[calledWith]()).toThrow(); + } + }); + + test("works when not called", () => { + const fn = jest.fn(); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn)).not[calledWith](1, "foo", "bar"); + jestExpect(fn).not[calledWith](1, "foo", "bar"); + + expect(() => jestExpect(fn)[calledWith](1, "foo", "bar")).toThrow(); + } else { + // jestExpect(createSpy(fn)).not[calledWith]("foo", "bar"); + jestExpect(fn).not[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn)[calledWith]("foo", "bar")).toThrow(); + } + }); + + test("works with no arguments", () => { + const fn = jest.fn(); + fn(); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn))[calledWith](1); + jestExpect(fn)[calledWith](1); + } else { + // jestExpect(createSpy(fn))[calledWith](); + jestExpect(fn)[calledWith](); + } + }); + + test("works with arguments that don't match", () => { + const fn = jest.fn(); + fn("foo", "bar1"); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn)).not[calledWith](1, "foo", "bar"); + jestExpect(fn).not[calledWith](1, "foo", "bar"); + + expect(() => jestExpect(fn)[calledWith](1, "foo", "bar")).toThrow(); + } else { + // jestExpect(createSpy(fn)).not[calledWith]("foo", "bar"); + jestExpect(fn).not[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn)[calledWith]("foo", "bar")).toThrow(); + } + }); + + test("works with arguments that don't match in number of arguments", () => { + const fn = jest.fn(); + fn("foo", "bar", "plop"); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn)).not[calledWith](1, "foo", "bar"); + jestExpect(fn).not[calledWith](1, "foo", "bar"); + + expect(() => jestExpect(fn)[calledWith](1, "foo", "bar")).toThrow(); + } else { + // jestExpect(createSpy(fn)).not[calledWith]("foo", "bar"); + jestExpect(fn).not[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn)[calledWith]("foo", "bar")).toThrow(); + } + }); + + test("works with arguments that don't match with matchers", () => { + const fn = jest.fn(); + fn("foo", "bar"); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn)).not[calledWith](1, jestExpect.any(String), jestExpect.any(Number)); + jestExpect(fn).not[calledWith](1, jestExpect.any(String), jestExpect.any(Number)); + + expect(() => jestExpect(fn)[calledWith](1, jestExpect.any(String), jestExpect.any(Number))).toThrow(); + } else { + // jestExpect(createSpy(fn)).not[calledWith](jestExpect.any(String), jestExpect.any(Number)); + jestExpect(fn).not[calledWith](jestExpect.any(String), jestExpect.any(Number)); + + expect(() => jestExpect(fn)[calledWith](jestExpect.any(String), jestExpect.any(Number))).toThrow(); + } + }); + + test("works with arguments that don't match with matchers even when argument is undefined", () => { + const fn = jest.fn(); + fn("foo", undefined); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn)).not[calledWith](1, "foo", jestExpect.any(String)); + jestExpect(fn).not[calledWith](1, "foo", jestExpect.any(String)); + + expect(() => jestExpect(fn)[calledWith](1, "foo", jestExpect.any(String))).toThrow(); + } else { + // jestExpect(createSpy(fn)).not[calledWith]("foo", jestExpect.any(String)); + jestExpect(fn).not[calledWith]("foo", jestExpect.any(String)); + + expect(() => jestExpect(fn)[calledWith]("foo", jestExpect.any(String))).toThrow(); + } + }); + + test("works with arguments that don't match in size even if one is an optional matcher", () => { + // issue 12463 + const fn = jest.fn(); + fn("foo"); + + if (isToHaveNth(calledWith)) { + jestExpect(fn).not[calledWith](1, "foo", jestExpect.optionalFn()); + expect(() => jestExpect(fn)[calledWith](1, "foo", jestExpect.optionalFn())).toThrow(); + } else { + jestExpect(fn).not[calledWith]("foo", jestExpect.optionalFn()); + expect(() => jestExpect(fn)[calledWith]("foo", jestExpect.optionalFn())).toThrow(); + } + }); + + test("works with arguments that match", () => { + const fn = jest.fn(); + fn("foo", "bar"); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn))[calledWith](1, "foo", "bar"); + jestExpect(fn)[calledWith](1, "foo", "bar"); + + expect(() => jestExpect(fn).not[calledWith](1, "foo", "bar")).toThrow(); + } else { + // jestExpect(createSpy(fn))[calledWith]("foo", "bar"); + jestExpect(fn)[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn).not[calledWith]("foo", "bar")).toThrow(); + } + }); + + test("works with arguments that match with matchers", () => { + const fn = jest.fn(); + fn("foo", "bar"); + + if (isToHaveNth(calledWith)) { + // jestExpect(createSpy(fn))[calledWith](1, jestExpect.any(String), jestExpect.any(String)); + jestExpect(fn)[calledWith](1, jestExpect.any(String), jestExpect.any(String)); + + expect(() => jestExpect(fn).not[calledWith](1, jestExpect.any(String), jestExpect.any(String))).toThrow(); + } else { + // jestExpect(createSpy(fn))[calledWith](jestExpect.any(String), jestExpect.any(String)); + jestExpect(fn)[calledWith](jestExpect.any(String), jestExpect.any(String)); + + expect(() => jestExpect(fn).not[calledWith](jestExpect.any(String), jestExpect.any(String))).toThrow(); + } + }); + + test("works with trailing undefined arguments", () => { + const fn = jest.fn(); + fn("foo", undefined); + + if (isToHaveNth(calledWith)) { + expect(() => jestExpect(fn)[calledWith](1, "foo")).toThrow(); + } else { + expect(() => jestExpect(fn)[calledWith]("foo")).toThrow(); + } + }); + + test("works with trailing undefined arguments if requested by the match query", () => { + const fn = jest.fn(); + fn("foo", undefined); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, "foo", undefined); + expect(() => jestExpect(fn).not[calledWith](1, "foo", undefined)).toThrow(); + } else { + jestExpect(fn)[calledWith]("foo", undefined); + expect(() => jestExpect(fn).not[calledWith]("foo", undefined)).toThrow(); + } + }); + + test("works with trailing undefined arguments when explicitly requested as optional by matcher", () => { + // issue 12463 + const fn = jest.fn(); + fn("foo", undefined); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, "foo", jestExpect.optionalFn()); + expect(() => jestExpect(fn).not[calledWith](1, "foo", jestExpect.optionalFn())).toThrow(); + } else { + jestExpect(fn)[calledWith]("foo", jestExpect.optionalFn()); + expect(() => jestExpect(fn).not[calledWith]("foo", jestExpect.optionalFn())).toThrow(); + } + }); + + test("works with Map", () => { + const fn = jest.fn(); + + const m1 = new Map([ + [1, 2], + [2, 1], + ]); + const m2 = new Map([ + [1, 2], + [2, 1], + ]); + const m3 = new Map([ + ["a", "b"], + ["b", "a"], + ]); + + fn(m1); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, m2); + jestExpect(fn).not[calledWith](1, m3); + + expect(() => jestExpect(fn).not[calledWith](1, m2)).toThrow(); + expect(() => jestExpect(fn)[calledWith](1, m3)).toThrow(); + } else { + jestExpect(fn)[calledWith](m2); + jestExpect(fn).not[calledWith](m3); + + expect(() => jestExpect(fn).not[calledWith](m2)).toThrow(); + expect(() => jestExpect(fn)[calledWith](m3)).toThrow(); + } + }); + + test("works with Set", () => { + const fn = jest.fn(); + + const s1 = new Set([1, 2]); + const s2 = new Set([1, 2]); + const s3 = new Set([3, 4]); + + fn(s1); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, s2); + jestExpect(fn).not[calledWith](1, s3); + + expect(() => jestExpect(fn).not[calledWith](1, s2)).toThrow(); + expect(() => jestExpect(fn)[calledWith](1, s3)).toThrow(); + } else { + jestExpect(fn)[calledWith](s2); + jestExpect(fn).not[calledWith](s3); + + expect(() => jestExpect(fn).not[calledWith](s2)).toThrow(); + expect(() => jestExpect(fn)[calledWith](s3)).toThrow(); + } + }); + + test.todo("works with Immutable.js objects", () => { + const fn = jest.fn(); + const directlyCreated = Immutable.Map([["a", { b: "c" }]]); + const indirectlyCreated = Immutable.Map().set("a", { b: "c" }); + fn(directlyCreated, indirectlyCreated); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, indirectlyCreated, directlyCreated); + + expect(() => jestExpect(fn).not[calledWith](1, indirectlyCreated, directlyCreated)).toThrow(); + } else { + jestExpect(fn)[calledWith](indirectlyCreated, directlyCreated); + + expect(() => jestExpect(fn).not[calledWith](indirectlyCreated, directlyCreated)).toThrow(); + } + }); + + if (!isToHaveNth(calledWith)) { + test("works with many arguments", () => { + const fn = jest.fn(); + fn("foo1", "bar"); + fn("foo", "bar1"); + fn("foo", "bar"); + + jestExpect(fn)[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn).not[calledWith]("foo", "bar")).toThrow(); + }); + + test("works with many arguments that don't match", () => { + const fn = jest.fn(); + fn("foo", "bar1"); + fn("foo", "bar2"); + fn("foo", "bar3"); + + jestExpect(fn).not[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn)[calledWith]("foo", "bar")).toThrow(); + }); + } + + if (isToHaveNth(calledWith)) { + test("works with three calls", () => { + const fn = jest.fn(); + fn("foo1", "bar"); + fn("foo", "bar1"); + fn("foo", "bar"); + + jestExpect(fn)[calledWith](1, "foo1", "bar"); + jestExpect(fn)[calledWith](2, "foo", "bar1"); + jestExpect(fn)[calledWith](3, "foo", "bar"); + + expect(() => { + jestExpect(fn).not[calledWith](1, "foo1", "bar"); + }).toThrow(); + }); + + test("positive throw matcher error for n that is not positive integer", async () => { + const fn = jest.fn(); + fn("foo1", "bar"); + + expect(() => { + jestExpect(fn)[calledWith](0, "foo1", "bar"); + }).toThrow(); + }); + + test("positive throw matcher error for n that is not integer", async () => { + const fn = jest.fn(); + fn("foo1", "bar"); + + expect(() => { + jestExpect(fn)[calledWith](0.1, "foo1", "bar"); + }).toThrow(); + }); + + test("negative throw matcher error for n that is not integer", async () => { + const fn = jest.fn(); + fn("foo1", "bar"); + + expect(() => { + jestExpect(fn).not[calledWith](Number.POSITIVE_INFINITY, "foo1", "bar"); + }).toThrow(); + }); + } + + test("includes the custom mock name in the error message", () => { + const fn = jest.fn().mockName("named-mock"); + fn("foo", "bar"); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, "foo", "bar"); + + expect(() => jestExpect(fn).not[calledWith](1, "foo", "bar")).toThrow(); + } else { + jestExpect(fn)[calledWith]("foo", "bar"); + + expect(() => jestExpect(fn).not[calledWith]("foo", "bar")).toThrow(); + } + }); + + test("works with objectContaining", () => { + const fn = jest.fn(); + // Call the function twice with different objects and verify that the + // correct comparison sample is still used (original sample isn't mutated) + fn({ a: 1, b: 2, c: 4 }); + fn({ a: 3, b: 7, c: 4 }); + + if (isToHaveNth(calledWith)) { + jestExpect(fn)[calledWith](1, jestExpect.objectContaining({ b: 2 })); + jestExpect(fn)[calledWith](2, jestExpect.objectContaining({ b: 7 })); + jestExpect(fn)[calledWith](2, jestExpect.not.objectContaining({ b: 2 })); + + expect(() => jestExpect(fn)[calledWith](1, jestExpect.objectContaining({ b: 7 }))).toThrow(); + + expect(() => jestExpect(fn).not[calledWith](1, jestExpect.objectContaining({ b: 2 }))).toThrow(); + + expect(() => jestExpect(fn)[calledWith](1, jestExpect.not.objectContaining({ b: 2 }))).toThrow(); + } else { + jestExpect(fn)[calledWith](jestExpect.objectContaining({ b: 7 })); + jestExpect(fn)[calledWith](jestExpect.not.objectContaining({ b: 3 })); + + // The function was never called with this value. + // Only {"b": 3} should be shown as the expected value in the snapshot + // (no extra properties in the expected value). + expect(() => jestExpect(fn)[calledWith](jestExpect.objectContaining({ b: 3 }))).toThrow(); + + // Only {"b": 7} should be shown in the snapshot. + expect(() => jestExpect(fn).not[calledWith](jestExpect.objectContaining({ b: 7 }))).toThrow(); + } + + if (calledWith === "toHaveBeenCalledWith") { + // The first call had {b: 2}, so this passes. + jestExpect(fn)[calledWith](jestExpect.not.objectContaining({ b: 7 })); + + // Only {"c": 4} should be shown in the snapshot. + expect(() => jestExpect(fn)[calledWith](jestExpect.not.objectContaining({ c: 4 }))).toThrow(); + } + }); + }, +); + +describe("toHaveReturned", () => { + test(".not works only on jest.fn", () => { + const fn = function fn() {}; + + expect(() => jestExpect(fn).not.toHaveReturned()).toThrow(); + }); + + test.todo("throw matcher error if received is spy", () => { + const spy = createSpy(jest.fn()); + + expect(() => jestExpect(spy).toHaveReturned()).toThrow(); + }); + + test("passes when returned", () => { + const fn = jest.fn(() => 42); + fn(); + jestExpect(fn).toHaveReturned(); + expect(() => jestExpect(fn).not.toHaveReturned()).toThrow(); + }); + + test("passes when undefined is returned", () => { + const fn = jest.fn(() => undefined); + fn(); + jestExpect(fn).toHaveReturned(); + expect(() => jestExpect(fn).not.toHaveReturned()).toThrow(); + }); + + test("passes when at least one call does not throw", () => { + const fn = jest.fn((causeError: boolean) => { + if (causeError) { + throw new Error("Error!"); + } + + return 42; + }); + + fn(false); + + try { + fn(true); + } catch { + // ignore error + } + + fn(false); + + jestExpect(fn).toHaveReturned(); + expect(() => jestExpect(fn).not.toHaveReturned()).toThrow(); + }); + + test(".not passes when not returned", () => { + const fn = jest.fn(); + + jestExpect(fn).not.toHaveReturned(); + expect(() => jestExpect(fn).toHaveReturned()).toThrow(); + }); + + test(".not passes when all calls throw", () => { + const fn = jest.fn(() => { + throw new Error("Error!"); + }); + + try { + fn(); + } catch { + // ignore error + } + + try { + fn(); + } catch { + // ignore error + } + + jestExpect(fn).not.toHaveReturned(); + expect(() => jestExpect(fn).toHaveReturned()).toThrow(); + }); + + test(".not passes when a call throws undefined", () => { + const fn = jest.fn(() => { + // eslint-disable-next-line no-throw-literal + throw undefined; + }); + + try { + fn(); + } catch { + // ignore error + } + + jestExpect(fn).not.toHaveReturned(); + expect(() => jestExpect(fn).toHaveReturned()).toThrow(); + }); + + test("fails with any argument passed", () => { + const fn = jest.fn(); + + fn(); + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).toHaveReturned(555), + ).toThrow(); + }); + + test(".not fails with any argument passed", () => { + const fn = jest.fn(); + + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).not.toHaveReturned(555), + ).toThrow(); + }); + + test("includes the custom mock name in the error message", () => { + const fn = jest.fn(() => 42).mockName("named-mock"); + fn(); + jestExpect(fn).toHaveReturned(); + expect(() => jestExpect(fn).not.toHaveReturned()).toThrow(); + }); + + test("incomplete recursive calls are handled properly", () => { + // sums up all integers from 0 -> value, using recursion + const fn: jest.Mock<(value: number) => number> = jest.fn(value => { + if (value === 0) { + // Before returning from the base case of recursion, none of the + // calls have returned yet. + jestExpect(fn).not.toHaveReturned(); + expect(() => jestExpect(fn).toHaveReturned()).toThrow(); + return 0; + } else { + return value + fn(value - 1); + } + }); + + fn(3); + }); +}); + +describe("toHaveReturnedTimes", () => { + test.todo("throw matcher error if received is spy", () => { + const spy = createSpy(jest.fn()); + + expect(() => jestExpect(spy).not.toHaveReturnedTimes(2)).toThrow(); + }); + + test("only accepts a number argument", () => { + const fn = jest.fn(() => 42); + fn(); + jestExpect(fn).toHaveReturnedTimes(1); + + for (const value of [{}, [], true, "a", new Map(), () => {}]) { + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).toHaveReturnedTimes(value), + ).toThrow(); + } + }); + + test(".not only accepts a number argument", () => { + const fn = jest.fn(() => 42); + jestExpect(fn).not.toHaveReturnedTimes(2); + + for (const value of [{}, [], true, "a", new Map(), () => {}]) { + expect(() => + // @ts-expect-error: Testing runtime error + jestExpect(fn).not.toHaveReturnedTimes(value), + ).toThrow(); + } + }); + + test("passes if function returned equal to expected times", () => { + const fn = jest.fn(() => 42); + fn(); + fn(); + + jestExpect(fn).toHaveReturnedTimes(2); + + expect(() => jestExpect(fn).not.toHaveReturnedTimes(2)).toThrow(); + }); + + test("calls that return undefined are counted as returns", () => { + const fn = jest.fn(() => undefined); + fn(); + fn(); + + jestExpect(fn).toHaveReturnedTimes(2); + + expect(() => jestExpect(fn).not.toHaveReturnedTimes(2)).toThrow(); + }); + + test(".not passes if function returned more than expected times", () => { + const fn = jest.fn(() => 42); + fn(); + fn(); + fn(); + + jestExpect(fn).toHaveReturnedTimes(3); + jestExpect(fn).not.toHaveReturnedTimes(2); + + expect(() => jestExpect(fn).toHaveReturnedTimes(2)).toThrow(); + }); + + test(".not passes if function called less than expected times", () => { + const fn = jest.fn(() => 42); + fn(); + + jestExpect(fn).toHaveReturnedTimes(1); + jestExpect(fn).not.toHaveReturnedTimes(2); + + expect(() => jestExpect(fn).toHaveReturnedTimes(2)).toThrow(); + }); + + test("calls that throw are not counted", () => { + const fn = jest.fn((causeError: boolean) => { + if (causeError) { + throw new Error("Error!"); + } + + return 42; + }); + + fn(false); + + try { + fn(true); + } catch { + // ignore error + } + + fn(false); + + jestExpect(fn).not.toHaveReturnedTimes(3); + + expect(() => jestExpect(fn).toHaveReturnedTimes(3)).toThrow(); + }); + + test("calls that throw undefined are not counted", () => { + const fn = jest.fn((causeError: boolean) => { + if (causeError) { + // eslint-disable-next-line no-throw-literal + throw undefined; + } + + return 42; + }); + + fn(false); + + try { + fn(true); + } catch { + // ignore error + } + + fn(false); + + jestExpect(fn).toHaveReturnedTimes(2); + + expect(() => jestExpect(fn).not.toHaveReturnedTimes(2)).toThrow(); + }); + + test("includes the custom mock name in the error message", () => { + const fn = jest.fn(() => 42).mockName("named-mock"); + fn(); + fn(); + + jestExpect(fn).toHaveReturnedTimes(2); + + expect(() => jestExpect(fn).toHaveReturnedTimes(1)).toThrow(); + }); + + test("incomplete recursive calls are handled properly", () => { + // sums up all integers from 0 -> value, using recursion + const fn: jest.Mock<(value: number) => number> = jest.fn(value => { + if (value === 0) { + return 0; + } else { + const recursiveResult = fn(value - 1); + + if (value === 2) { + // Only 2 of the recursive calls have returned at this point + jestExpect(fn).toHaveReturnedTimes(2); + expect(() => jestExpect(fn).not.toHaveReturnedTimes(2)).toThrow(); + } + + return value + recursiveResult; + } + }); + + fn(3); + }); +}); + +describe.each(["toHaveLastReturnedWith", "toHaveNthReturnedWith", "toHaveReturnedWith"] as const)( + "%s", + returnedWith => { + function isToHaveNth(returnedWith: string): returnedWith is "toHaveNthReturnedWith" { + return returnedWith === "toHaveNthReturnedWith"; + } + + function isToHaveLast(returnedWith: string): returnedWith is "toHaveLastReturnedWith" { + return returnedWith === "toHaveLastReturnedWith"; + } + test("works only on spies or jest.fn", () => { + const fn = function fn() {}; + + // @ts-expect-error: Testing runtime error + expect(() => jestExpect(fn)[returnedWith]()).toThrow(); + }); + + test("works when not called", () => { + const fn = jest.fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn).not[returnedWith](1, "foo"); + + expect(() => jestExpect(fn)[returnedWith](1, "foo")).toThrow(); + } else { + jestExpect(fn).not[returnedWith]("foo"); + + expect(() => jestExpect(fn)[returnedWith]("foo")).toThrow(); + } + }); + + test("works with no arguments", () => { + const fn = jest.fn(); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1); + } else { + jestExpect(fn)[returnedWith](); + } + }); + + test("works with argument that does not match", () => { + const fn = jest.fn(() => "foo"); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn).not[returnedWith](1, "bar"); + + expect(() => jestExpect(fn)[returnedWith](1, "bar")).toThrow(); + } else { + jestExpect(fn).not[returnedWith]("bar"); + + expect(() => jestExpect(fn)[returnedWith]("bar")).toThrow(); + } + }); + + test("works with argument that does match", () => { + const fn = jest.fn(() => "foo"); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1, "foo"); + + expect(() => jestExpect(fn).not[returnedWith](1, "foo")).toThrow(); + } else { + jestExpect(fn)[returnedWith]("foo"); + + expect(() => jestExpect(fn).not[returnedWith]("foo")).toThrow(); + } + }); + + test("works with undefined", () => { + const fn = jest.fn(() => undefined); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1, undefined); + + expect(() => jestExpect(fn).not[returnedWith](1, undefined)).toThrow(); + } else { + jestExpect(fn)[returnedWith](undefined); + + expect(() => jestExpect(fn).not[returnedWith](undefined)).toThrow(); + } + }); + + test("works with Map", () => { + const m1 = new Map([ + [1, 2], + [2, 1], + ]); + const m2 = new Map([ + [1, 2], + [2, 1], + ]); + const m3 = new Map([ + ["a", "b"], + ["b", "a"], + ]); + + const fn = jest.fn(() => m1); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1, m2); + jestExpect(fn).not[returnedWith](1, m3); + + expect(() => jestExpect(fn).not[returnedWith](1, m2)).toThrow(); + expect(() => jestExpect(fn)[returnedWith](1, m3)).toThrow(); + } else { + jestExpect(fn)[returnedWith](m2); + jestExpect(fn).not[returnedWith](m3); + + expect(() => jestExpect(fn).not[returnedWith](m2)).toThrow(); + expect(() => jestExpect(fn)[returnedWith](m3)).toThrow(); + } + }); + + test("works with Set", () => { + const s1 = new Set([1, 2]); + const s2 = new Set([1, 2]); + const s3 = new Set([3, 4]); + + const fn = jest.fn(() => s1); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1, s2); + jestExpect(fn).not[returnedWith](1, s3); + + expect(() => jestExpect(fn).not[returnedWith](1, s2)).toThrow(); + expect(() => jestExpect(fn)[returnedWith](1, s3)).toThrow(); + } else { + jestExpect(fn)[returnedWith](s2); + jestExpect(fn).not[returnedWith](s3); + + expect(() => jestExpect(fn).not[returnedWith](s2)).toThrow(); + expect(() => jestExpect(fn)[returnedWith](s3)).toThrow(); + } + }); + + test("works with Immutable.js objects directly created", () => { + const directlyCreated = Immutable.Map([["a", { b: "c" }]]); + const fn = jest.fn(() => directlyCreated); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1, directlyCreated); + + expect(() => jestExpect(fn).not[returnedWith](1, directlyCreated)).toThrow(); + } else { + jestExpect(fn)[returnedWith](directlyCreated); + + expect(() => jestExpect(fn).not[returnedWith](directlyCreated)).toThrow(); + } + }); + + test("works with Immutable.js objects indirectly created", () => { + const indirectlyCreated = Immutable.Map().set("a", { b: "c" }); + const fn = jest.fn(() => indirectlyCreated); + fn(); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn)[returnedWith](1, indirectlyCreated); + + expect(() => jestExpect(fn).not[returnedWith](1, indirectlyCreated)).toThrow(); + } else { + jestExpect(fn)[returnedWith](indirectlyCreated); + + expect(() => jestExpect(fn).not[returnedWith](indirectlyCreated)).toThrow(); + } + }); + + test("a call that throws is not considered to have returned", () => { + const fn = jest.fn(() => { + throw new Error("Error!"); + }); + + try { + fn(); + } catch { + // ignore error + } + + if (isToHaveNth(returnedWith)) { + // It doesn't matter what return value is tested if the call threw + jestExpect(fn).not[returnedWith](1, "foo"); + jestExpect(fn).not[returnedWith](1, null); + jestExpect(fn).not[returnedWith](1, undefined); + + expect(() => jestExpect(fn)[returnedWith](1, undefined)).toThrow(); + } else { + // It doesn't matter what return value is tested if the call threw + jestExpect(fn).not[returnedWith]("foo"); + jestExpect(fn).not[returnedWith](null); + jestExpect(fn).not[returnedWith](undefined); + + expect(() => jestExpect(fn)[returnedWith](undefined)).toThrow(); + } + }); + + test("a call that throws undefined is not considered to have returned", () => { + const fn = jest.fn(() => { + // eslint-disable-next-line no-throw-literal + throw undefined; + }); + + try { + fn(); + } catch { + // ignore error + } + + if (isToHaveNth(returnedWith)) { + // It doesn't matter what return value is tested if the call threw + jestExpect(fn).not[returnedWith](1, "foo"); + jestExpect(fn).not[returnedWith](1, null); + jestExpect(fn).not[returnedWith](1, undefined); + + expect(() => jestExpect(fn)[returnedWith](1, undefined)).toThrow(); + } else { + // It doesn't matter what return value is tested if the call threw + jestExpect(fn).not[returnedWith]("foo"); + jestExpect(fn).not[returnedWith](null); + jestExpect(fn).not[returnedWith](undefined); + + expect(() => jestExpect(fn)[returnedWith](undefined)).toThrow(); + } + }); + + if (!isToHaveNth(returnedWith)) { + describe("toHaveReturnedWith", () => { + test("works with more calls than the limit", () => { + const fn = jest.fn<() => string>(); + fn.mockReturnValueOnce("foo1"); + fn.mockReturnValueOnce("foo2"); + fn.mockReturnValueOnce("foo3"); + fn.mockReturnValueOnce("foo4"); + fn.mockReturnValueOnce("foo5"); + fn.mockReturnValueOnce("foo6"); + + fn(); + fn(); + fn(); + fn(); + fn(); + fn(); + + jestExpect(fn).not[returnedWith]("bar"); + + expect(() => { + jestExpect(fn)[returnedWith]("bar"); + }).toThrow(); + }); + + test("incomplete recursive calls are handled properly", () => { + // sums up all integers from 0 -> value, using recursion + const fn: jest.Mock<(value: number) => number> = jest.fn(value => { + if (value === 0) { + // Before returning from the base case of recursion, none of the + // calls have returned yet. + // This test ensures that the incomplete calls are not incorrectly + // interpreted as have returned undefined + jestExpect(fn).not[returnedWith](undefined); + expect(() => jestExpect(fn)[returnedWith](undefined)).toThrow(); + + return 0; + } else { + return value + fn(value - 1); + } + }); + + fn(3); + }); + }); + } + + if (isToHaveNth(returnedWith)) { + describe("toHaveNthReturnedWith", () => { + test("works with three calls", () => { + const fn = jest.fn<() => string>(); + fn.mockReturnValueOnce("foo1"); + fn.mockReturnValueOnce("foo2"); + fn.mockReturnValueOnce("foo3"); + fn(); + fn(); + fn(); + + jestExpect(fn)[returnedWith](1, "foo1"); + jestExpect(fn)[returnedWith](2, "foo2"); + jestExpect(fn)[returnedWith](3, "foo3"); + + expect(() => { + jestExpect(fn).not[returnedWith](1, "foo1"); + jestExpect(fn).not[returnedWith](2, "foo2"); + jestExpect(fn).not[returnedWith](3, "foo3"); + }).toThrow(); + }); + + test("should replace 1st, 2nd, 3rd with first, second, third", async () => { + const fn = jest.fn<() => string>(); + fn.mockReturnValueOnce("foo1"); + fn.mockReturnValueOnce("foo2"); + fn.mockReturnValueOnce("foo3"); + fn(); + fn(); + fn(); + + expect(() => { + jestExpect(fn)[returnedWith](1, "bar1"); + jestExpect(fn)[returnedWith](2, "bar2"); + jestExpect(fn)[returnedWith](3, "bar3"); + }).toThrow(); + + expect(() => { + jestExpect(fn).not[returnedWith](1, "foo1"); + jestExpect(fn).not[returnedWith](2, "foo2"); + jestExpect(fn).not[returnedWith](3, "foo3"); + }).toThrow(); + }); + + test("positive throw matcher error for n that is not positive integer", async () => { + const fn = jest.fn(() => "foo"); + fn(); + + expect(() => { + jestExpect(fn)[returnedWith](0, "foo"); + }).toThrow(); + }); + + test("should reject nth value greater than number of calls", async () => { + const fn = jest.fn(() => "foo"); + fn(); + fn(); + fn(); + + expect(() => { + jestExpect(fn)[returnedWith](4, "foo"); + }).toThrow(); + }); + + test("positive throw matcher error for n that is not integer", async () => { + const fn = jest.fn<(a: string) => string>(() => "foo"); + fn("foo"); + + expect(() => { + jestExpect(fn)[returnedWith](0.1, "foo"); + }).toThrow(); + }); + + test("negative throw matcher error for n that is not number", async () => { + const fn = jest.fn<(a: string) => string>(() => "foo"); + fn("foo"); + + expect(() => { + // @ts-expect-error: Testing runtime error + jestExpect(fn).not[returnedWith](); + }).toThrow(); + }); + + test("incomplete recursive calls are handled properly", () => { + // sums up all integers from 0 -> value, using recursion + const fn: jest.Mock<(value: number) => number> = jest.fn(value => { + if (value === 0) { + return 0; + } else { + const recursiveResult = fn(value - 1); + + if (value === 2) { + // Only 2 of the recursive calls have returned at this point + jestExpect(fn).not[returnedWith](1, 6); + jestExpect(fn).not[returnedWith](2, 3); + jestExpect(fn)[returnedWith](3, 1); + jestExpect(fn)[returnedWith](4, 0); + + expect(() => jestExpect(fn)[returnedWith](1, 6)).toThrow(); + expect(() => jestExpect(fn)[returnedWith](2, 3)).toThrow(); + expect(() => jestExpect(fn).not[returnedWith](3, 1)).toThrow(); + expect(() => jestExpect(fn).not[returnedWith](4, 0)).toThrow(); + } + + return value + recursiveResult; + } + }); + + fn(3); + }); + }); + } + + if (isToHaveLast(returnedWith)) { + describe("toHaveLastReturnedWith", () => { + test("works with three calls", () => { + const fn = jest.fn<() => string>(); + fn.mockReturnValueOnce("foo1"); + fn.mockReturnValueOnce("foo2"); + fn.mockReturnValueOnce("foo3"); + fn(); + fn(); + fn(); + + jestExpect(fn)[returnedWith]("foo3"); + + expect(() => { + jestExpect(fn).not[returnedWith]("foo3"); + }).toThrow(); + }); + + test("incomplete recursive calls are handled properly", () => { + // sums up all integers from 0 -> value, using recursion + const fn: jest.Mock<(value: number) => number> = jest.fn(value => { + if (value === 0) { + // Before returning from the base case of recursion, none of the + // calls have returned yet. + jestExpect(fn).not[returnedWith](0); + expect(() => jestExpect(fn)[returnedWith](0)).toThrow(); + return 0; + } else { + return value + fn(value - 1); + } + }); + + fn(3); + }); + }); + } + + test("includes the custom mock name in the error message", () => { + const fn = jest.fn().mockName("named-mock"); + + if (isToHaveNth(returnedWith)) { + jestExpect(fn).not[returnedWith](1, "foo"); + + expect(() => jestExpect(fn)[returnedWith](1, "foo")).toThrow(); + } else { + jestExpect(fn).not[returnedWith]("foo"); + + expect(() => jestExpect(fn)[returnedWith]("foo")).toThrow(); + } + }); + }, +); diff --git a/test/js/bun/test/test-failing.test.ts b/test/js/bun/test/test-failing.test.ts index 7217d5378b..982a379b0f 100644 --- a/test/js/bun/test/test-failing.test.ts +++ b/test/js/bun/test/test-failing.test.ts @@ -24,13 +24,28 @@ describe("test.failing", () => { }); it("fails if no error is thrown or promise resolves", async () => { - const result = await $.cwd(fixtureDir).nothrow()`${bunExe()} test ./failing-test-passes.fixture.ts`.quiet(); + const result = await $.cwd( + fixtureDir, + ).nothrow()`FORCE_COLOR=0 ${bunExe()} test ./failing-test-passes.fixture.ts`.quiet(); const stderr = result.stderr.toString(); if (result.exitCode === 0) { fail("Expected exit code to be non-zero\n\n" + stderr); } expect(stderr).toContain(" 2 fail\n"); - expect(stderr).toContain("this test is marked as failing but it passed"); + expect(stderr.replaceAll(/ \[[\d.]+ms\]/g, "")).toMatchInlineSnapshot(` + " + failing-test-passes.fixture.ts: + (fail) This should fail but it doesnt + ^ this test is marked as failing but it passed. Remove \`.failing\` if tested behavior now works + (fail) This should fail but it doesnt (async) + ^ this test is marked as failing but it passed. Remove \`.failing\` if tested behavior now works + + 0 pass + 2 fail + 2 expect() calls + Ran 2 tests across 1 file. + " + `); }); it("timeouts still count as failures", async () => { diff --git a/test/js/node/http2/http2-helpers.cjs b/test/js/node/http2/http2-helpers.cjs index 1a2a927cef..c6208588d0 100644 --- a/test/js/node/http2/http2-helpers.cjs +++ b/test/js/node/http2/http2-helpers.cjs @@ -5,11 +5,11 @@ module.exports.TLS_CERT = TLS_CERT; module.exports.TLS_OPTIONS = { ca: TLS_CERT.cert }; const nodeExecutable = typeof Bun !== "undefined" ? Bun.which("node") : "node"; -exports.nodeEchoServer = async function nodeEchoServer() { +exports.nodeEchoServer = async function nodeEchoServer(paddingStrategy = 0) { if (!nodeExecutable) throw new Error("node executable not found"); const subprocess = require("child_process").spawn( nodeExecutable, - [path.join(__dirname, "node-echo-server.fixture.js"), JSON.stringify(TLS_CERT)], + [path.join(__dirname, "node-echo-server.fixture.js"), JSON.stringify(TLS_CERT), paddingStrategy ?? 0], { stdout: "pipe", stderr: "inherit", diff --git a/test/js/node/http2/node-echo-server.fixture.js b/test/js/node/http2/node-echo-server.fixture.js index e993e6a234..24487ae700 100644 --- a/test/js/node/http2/node-echo-server.fixture.js +++ b/test/js/node/http2/node-echo-server.fixture.js @@ -1,8 +1,10 @@ const http2 = require("http2"); const fs = require("fs"); +const paddingStrategy = process.argv[3]; const server = http2.createSecureServer({ ...JSON.parse(process.argv[2]), rejectUnauthorized: false, + paddingStrategy: paddingStrategy ?? http2.constants.PADDING_STRATEGY_NONE, }); const setCookie = ["a=b", "c=d; Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly", "e=f"]; diff --git a/test/js/node/http2/node-http2.test.js b/test/js/node/http2/node-http2.test.js index 4b01bc1177..ccab660fe2 100644 --- a/test/js/node/http2/node-http2.test.js +++ b/test/js/node/http2/node-http2.test.js @@ -19,106 +19,84 @@ function invalidArgTypeHelper(input) { if (typeof input == "string") return ` Received type string ('${input}')`; return ` Received type ${typeof input} (${input})`; } + +function paddingStrategyName(paddingStrategy) { + switch (paddingStrategy) { + case http2.constants.PADDING_STRATEGY_NONE: + return "none"; + case http2.constants.PADDING_STRATEGY_MAX: + return "max"; + case http2.constants.PADDING_STRATEGY_ALIGNED: + return "aligned"; + } +} + for (const nodeExecutable of [nodeExe(), bunExe()]) { - describe(`${path.basename(nodeExecutable)}`, () => { - let nodeEchoServer_; + for (const paddingStrategy of [ + http2.constants.PADDING_STRATEGY_NONE, + http2.constants.PADDING_STRATEGY_MAX, + http2.constants.PADDING_STRATEGY_ALIGNED, + ]) { + describe(`${path.basename(nodeExecutable)} ${paddingStrategyName(paddingStrategy)}`, () => { + let nodeEchoServer_; - let HTTPS_SERVER; - beforeEach(async () => { - nodeEchoServer_ = await nodeEchoServer(); - HTTPS_SERVER = nodeEchoServer_.url; - }); - afterEach(async () => { - nodeEchoServer_.subprocess?.kill?.(9); - }); + let HTTPS_SERVER; + beforeEach(async () => { + nodeEchoServer_ = await nodeEchoServer(paddingStrategy); + HTTPS_SERVER = nodeEchoServer_.url; + }); + afterEach(async () => { + nodeEchoServer_.subprocess?.kill?.(9); + }); - async function nodeDynamicServer(test_name, code) { - if (!nodeExecutable) throw new Error("node executable not found"); + async function nodeDynamicServer(test_name, code) { + if (!nodeExecutable) throw new Error("node executable not found"); - const tmp_dir = path.join(fs.realpathSync(tmpdir()), "http.nodeDynamicServer"); - if (!fs.existsSync(tmp_dir)) { - fs.mkdirSync(tmp_dir, { recursive: true }); - } + const tmp_dir = path.join(fs.realpathSync(tmpdir()), "http.nodeDynamicServer"); + if (!fs.existsSync(tmp_dir)) { + fs.mkdirSync(tmp_dir, { recursive: true }); + } - const file_name = path.join(tmp_dir, test_name); - const contents = Buffer.from(`const http2 = require("http2"); - const server = http2.createServer(); + const file_name = path.join(tmp_dir, test_name); + const contents = Buffer.from(`const http2 = require("http2"); + const server = http2.createServer({ paddingStrategy: ${paddingStrategy} }); ${code} server.listen(0); server.on("listening", () => { process.stdout.write(JSON.stringify(server.address())); });`); - fs.writeFileSync(file_name, contents); + fs.writeFileSync(file_name, contents); - const subprocess = Bun.spawn([nodeExecutable, file_name, JSON.stringify(TLS_CERT)], { - stdout: "pipe", - stdin: "inherit", - stderr: "inherit", - env: bunEnv, - }); - subprocess.unref(); - const reader = subprocess.stdout.getReader(); - const data = await reader.read(); - const decoder = new TextDecoder("utf-8"); - const text = decoder.decode(data.value); - const address = JSON.parse(text); - const url = `http://${address.family === "IPv6" ? `[${address.address}]` : address.address}:${address.port}`; - return { address, url, subprocess }; - } - - function doHttp2Request(url, headers, payload, options, request_options) { - const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); - if (url.startsWith(HTTPS_SERVER)) { - options = { ...(options || {}), rejectUnauthorized: true, ...TLS_OPTIONS }; + const subprocess = Bun.spawn([nodeExecutable, file_name, JSON.stringify(TLS_CERT)], { + stdout: "pipe", + stdin: "inherit", + stderr: "inherit", + env: bunEnv, + }); + subprocess.unref(); + const reader = subprocess.stdout.getReader(); + const data = await reader.read(); + const decoder = new TextDecoder("utf-8"); + const text = decoder.decode(data.value); + const address = JSON.parse(text); + const url = `http://${address.family === "IPv6" ? `[${address.address}]` : address.address}:${address.port}`; + return { address, url, subprocess }; } - const client = options ? http2.connect(url, options) : http2.connect(url); - client.on("error", promiseReject); - function reject(err) { - promiseReject(err); - client.close(); - } + function doHttp2Request(url, headers, payload, options, request_options) { + const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); + if (url.startsWith(HTTPS_SERVER)) { + options = { ...(options || {}), rejectUnauthorized: true, ...TLS_OPTIONS }; + } - const req = request_options ? client.request(headers, request_options) : client.request(headers); + const client = options ? http2.connect(url, options) : http2.connect(url); + client.on("error", promiseReject); + function reject(err) { + promiseReject(err); + client.close(); + } - let response_headers = null; - req.on("response", (headers, flags) => { - response_headers = headers; - }); - - req.setEncoding("utf8"); - let data = ""; - req.on("data", chunk => { - data += chunk; - }); - req.on("error", reject); - req.on("end", () => { - resolve({ data, headers: response_headers }); - client.close(); - }); - - if (payload) { - req.write(payload); - } - req.end(); - return promise; - } - - function doMultiplexHttp2Request(url, requests) { - const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); - const client = http2.connect(url, TLS_OPTIONS); - - client.on("error", promiseReject); - function reject(err) { - promiseReject(err); - client.close(); - } - let completed = 0; - const results = []; - for (let i = 0; i < requests.length; i++) { - const { headers, payload } = requests[i]; - - const req = client.request(headers); + const req = request_options ? client.request(headers, request_options) : client.request(headers); let response_headers = null; req.on("response", (headers, flags) => { @@ -132,1189 +110,1231 @@ for (const nodeExecutable of [nodeExe(), bunExe()]) { }); req.on("error", reject); req.on("end", () => { - results.push({ data, headers: response_headers }); - completed++; - if (completed === requests.length) { - resolve(results); - client.close(); - } + resolve({ data, headers: response_headers }); + client.close(); }); if (payload) { req.write(payload); } req.end(); + return promise; } - return promise; - } - describe("Client Basics", () => { - // we dont support server yet but we support client - it("should be able to send a GET request", async () => { - const result = await doHttp2Request(HTTPS_SERVER, { ":path": "/get", "test-header": "test-value" }); - let parsed; - expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); - expect(parsed.url).toBe(`${HTTPS_SERVER}/get`); - expect(parsed.headers["test-header"]).toBe("test-value"); - }); - it("should be able to send a POST request", async () => { - const payload = JSON.stringify({ "hello": "bun" }); - const result = await doHttp2Request( - HTTPS_SERVER, - { ":path": "/post", "test-header": "test-value", ":method": "POST" }, - payload, - ); - let parsed; - expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); - expect(parsed.url).toBe(`${HTTPS_SERVER}/post`); - expect(parsed.headers["test-header"]).toBe("test-value"); - expect(parsed.json).toEqual({ "hello": "bun" }); - expect(parsed.data).toEqual(payload); - }); - it("should be able to send data using end", async () => { - const payload = JSON.stringify({ "hello": "bun" }); - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - const req = client.request({ ":path": "/post", "test-header": "test-value", ":method": "POST" }); - let response_headers = null; - req.on("response", (headers, flags) => { - response_headers = headers; - }); - req.setEncoding("utf8"); - let data = ""; - req.on("data", chunk => { - data += chunk; - }); - req.on("end", () => { - resolve({ data, headers: response_headers }); + function doMultiplexHttp2Request(url, requests) { + const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); + const client = http2.connect(url, TLS_OPTIONS); + + client.on("error", promiseReject); + function reject(err) { + promiseReject(err); client.close(); - }); - req.end(payload); - const result = await promise; - let parsed; - expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); - expect(parsed.url).toBe(`${HTTPS_SERVER}/post`); - expect(parsed.headers["test-header"]).toBe("test-value"); - expect(parsed.json).toEqual({ "hello": "bun" }); - expect(parsed.data).toEqual(payload); - }); - it("should be able to mutiplex GET requests", async () => { - const results = await doMultiplexHttp2Request(HTTPS_SERVER, [ - { headers: { ":path": "/get" } }, - { headers: { ":path": "/get" } }, - { headers: { ":path": "/get" } }, - { headers: { ":path": "/get" } }, - { headers: { ":path": "/get" } }, - ]); - expect(results.length).toBe(5); - for (let i = 0; i < results.length; i++) { - let parsed; - expect(() => (parsed = JSON.parse(results[i].data))).not.toThrow(); - expect(parsed.url).toBe(`${HTTPS_SERVER}/get`); } - }); - it("http2 should receive remoteSettings when receiving default settings frame", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const session = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + let completed = 0; + const results = []; + for (let i = 0; i < requests.length; i++) { + const { headers, payload } = requests[i]; - session.once("remoteSettings", resolve); - session.once("close", () => { - reject(new Error("Failed to receive remoteSettings")); + const req = client.request(headers, { + paddingStrategy: paddingStrategy, + }); + + let response_headers = null; + req.on("response", (headers, flags) => { + response_headers = headers; + }); + + req.setEncoding("utf8"); + let data = ""; + req.on("data", chunk => { + data += chunk; + }); + req.on("error", reject); + req.on("end", () => { + results.push({ data, headers: response_headers }); + completed++; + if (completed === requests.length) { + resolve(results); + client.close(); + } + }); + + if (payload) { + req.write(payload); + } + req.end(); + } + return promise; + } + + describe("Client Basics", () => { + // we dont support server yet but we support client + it("should be able to send a GET request", async () => { + const result = await doHttp2Request(HTTPS_SERVER, { ":path": "/get", "test-header": "test-value" }); + let parsed; + expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); + expect(parsed.url).toBe(`${HTTPS_SERVER}/get`); + expect(parsed.headers["test-header"]).toBe("test-value"); }); - try { - const settings = await promise; - expect(settings).toBeDefined(); + it("should be able to send a POST request", async () => { + const payload = JSON.stringify({ "hello": "bun" }); + const result = await doHttp2Request( + HTTPS_SERVER, + { ":path": "/post", "test-header": "test-value", ":method": "POST" }, + payload, + ); + let parsed; + expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); + expect(parsed.url).toBe(`${HTTPS_SERVER}/post`); + expect(parsed.headers["test-header"]).toBe("test-value"); + expect(parsed.json).toEqual({ "hello": "bun" }); + expect(parsed.data).toEqual(payload); + }); + it("should be able to send data using end", async () => { + const payload = JSON.stringify({ "hello": "bun" }); + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + const req = client.request({ ":path": "/post", "test-header": "test-value", ":method": "POST" }); + let response_headers = null; + req.on("response", (headers, flags) => { + response_headers = headers; + }); + req.setEncoding("utf8"); + let data = ""; + req.on("data", chunk => { + data += chunk; + }); + req.on("end", () => { + resolve({ data, headers: response_headers }); + client.close(); + }); + req.end(payload); + const result = await promise; + let parsed; + expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); + expect(parsed.url).toBe(`${HTTPS_SERVER}/post`); + expect(parsed.headers["test-header"]).toBe("test-value"); + expect(parsed.json).toEqual({ "hello": "bun" }); + expect(parsed.data).toEqual(payload); + }); + it("should be able to mutiplex GET requests", async () => { + const results = await doMultiplexHttp2Request(HTTPS_SERVER, [ + { headers: { ":path": "/get" } }, + { headers: { ":path": "/get" } }, + { headers: { ":path": "/get" } }, + { headers: { ":path": "/get" } }, + { headers: { ":path": "/get" } }, + ]); + expect(results.length).toBe(5); + for (let i = 0; i < results.length; i++) { + let parsed; + expect(() => (parsed = JSON.parse(results[i].data))).not.toThrow(); + expect(parsed.url).toBe(`${HTTPS_SERVER}/get`); + } + }); + it("http2 should receive remoteSettings when receiving default settings frame", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const session = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + + session.once("remoteSettings", resolve); + session.once("close", () => { + reject(new Error("Failed to receive remoteSettings")); + }); + try { + const settings = await promise; + expect(settings).toBeDefined(); + expect(settings).toEqual({ + headerTableSize: 4096, + enablePush: false, + maxConcurrentStreams: 4294967295, + initialWindowSize: 65535, + maxFrameSize: 16384, + maxHeaderListSize: 65535, + maxHeaderSize: 65535, + enableConnectProtocol: false, + }); + } finally { + session.close(); + } + }); + it("should be able to mutiplex POST requests", async () => { + const results = await doMultiplexHttp2Request(HTTPS_SERVER, [ + { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 1 }) }, + { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 2 }) }, + { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 3 }) }, + { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 4 }) }, + { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 5 }) }, + ]); + expect(results.length).toBe(5); + for (let i = 0; i < results.length; i++) { + let parsed; + expect(() => (parsed = JSON.parse(results[i].data))).not.toThrow(); + expect(parsed.url).toBe(`${HTTPS_SERVER}/post`); + expect([1, 2, 3, 4, 5]).toContain(parsed.json?.request); + } + }); + it("constants", () => { + expect(http2.constants).toEqual({ + "NGHTTP2_ERR_FRAME_SIZE_ERROR": -522, + "NGHTTP2_SESSION_SERVER": 0, + "NGHTTP2_SESSION_CLIENT": 1, + "NGHTTP2_STREAM_STATE_IDLE": 1, + "NGHTTP2_STREAM_STATE_OPEN": 2, + "NGHTTP2_STREAM_STATE_RESERVED_LOCAL": 3, + "NGHTTP2_STREAM_STATE_RESERVED_REMOTE": 4, + "NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL": 5, + "NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE": 6, + "NGHTTP2_STREAM_STATE_CLOSED": 7, + "NGHTTP2_FLAG_NONE": 0, + "NGHTTP2_FLAG_END_STREAM": 1, + "NGHTTP2_FLAG_END_HEADERS": 4, + "NGHTTP2_FLAG_ACK": 1, + "NGHTTP2_FLAG_PADDED": 8, + "NGHTTP2_FLAG_PRIORITY": 32, + "DEFAULT_SETTINGS_HEADER_TABLE_SIZE": 4096, + "DEFAULT_SETTINGS_ENABLE_PUSH": 1, + "DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS": 4294967295, + "DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE": 65535, + "DEFAULT_SETTINGS_MAX_FRAME_SIZE": 16384, + "DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE": 65535, + "DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL": 0, + "MAX_MAX_FRAME_SIZE": 16777215, + "MIN_MAX_FRAME_SIZE": 16384, + "MAX_INITIAL_WINDOW_SIZE": 2147483647, + "NGHTTP2_SETTINGS_HEADER_TABLE_SIZE": 1, + "NGHTTP2_SETTINGS_ENABLE_PUSH": 2, + "NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS": 3, + "NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE": 4, + "NGHTTP2_SETTINGS_MAX_FRAME_SIZE": 5, + "NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE": 6, + "NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL": 8, + "PADDING_STRATEGY_NONE": 0, + "PADDING_STRATEGY_ALIGNED": 1, + "PADDING_STRATEGY_MAX": 2, + "PADDING_STRATEGY_CALLBACK": 1, + "NGHTTP2_NO_ERROR": 0, + "NGHTTP2_PROTOCOL_ERROR": 1, + "NGHTTP2_INTERNAL_ERROR": 2, + "NGHTTP2_FLOW_CONTROL_ERROR": 3, + "NGHTTP2_SETTINGS_TIMEOUT": 4, + "NGHTTP2_STREAM_CLOSED": 5, + "NGHTTP2_FRAME_SIZE_ERROR": 6, + "NGHTTP2_REFUSED_STREAM": 7, + "NGHTTP2_CANCEL": 8, + "NGHTTP2_COMPRESSION_ERROR": 9, + "NGHTTP2_CONNECT_ERROR": 10, + "NGHTTP2_ENHANCE_YOUR_CALM": 11, + "NGHTTP2_INADEQUATE_SECURITY": 12, + "NGHTTP2_HTTP_1_1_REQUIRED": 13, + "NGHTTP2_DEFAULT_WEIGHT": 16, + "HTTP2_HEADER_STATUS": ":status", + "HTTP2_HEADER_METHOD": ":method", + "HTTP2_HEADER_AUTHORITY": ":authority", + "HTTP2_HEADER_SCHEME": ":scheme", + "HTTP2_HEADER_PATH": ":path", + "HTTP2_HEADER_PROTOCOL": ":protocol", + "HTTP2_HEADER_ACCEPT_ENCODING": "accept-encoding", + "HTTP2_HEADER_ACCEPT_LANGUAGE": "accept-language", + "HTTP2_HEADER_ACCEPT_RANGES": "accept-ranges", + "HTTP2_HEADER_ACCEPT": "accept", + "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS": "access-control-allow-credentials", + "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS": "access-control-allow-headers", + "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS": "access-control-allow-methods", + "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN": "access-control-allow-origin", + "HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS": "access-control-expose-headers", + "HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS": "access-control-request-headers", + "HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD": "access-control-request-method", + "HTTP2_HEADER_AGE": "age", + "HTTP2_HEADER_AUTHORIZATION": "authorization", + "HTTP2_HEADER_CACHE_CONTROL": "cache-control", + "HTTP2_HEADER_CONNECTION": "connection", + "HTTP2_HEADER_CONTENT_DISPOSITION": "content-disposition", + "HTTP2_HEADER_CONTENT_ENCODING": "content-encoding", + "HTTP2_HEADER_CONTENT_LENGTH": "content-length", + "HTTP2_HEADER_CONTENT_TYPE": "content-type", + "HTTP2_HEADER_COOKIE": "cookie", + "HTTP2_HEADER_DATE": "date", + "HTTP2_HEADER_ETAG": "etag", + "HTTP2_HEADER_FORWARDED": "forwarded", + "HTTP2_HEADER_HOST": "host", + "HTTP2_HEADER_IF_MODIFIED_SINCE": "if-modified-since", + "HTTP2_HEADER_IF_NONE_MATCH": "if-none-match", + "HTTP2_HEADER_IF_RANGE": "if-range", + "HTTP2_HEADER_LAST_MODIFIED": "last-modified", + "HTTP2_HEADER_LINK": "link", + "HTTP2_HEADER_LOCATION": "location", + "HTTP2_HEADER_RANGE": "range", + "HTTP2_HEADER_REFERER": "referer", + "HTTP2_HEADER_SERVER": "server", + "HTTP2_HEADER_SET_COOKIE": "set-cookie", + "HTTP2_HEADER_STRICT_TRANSPORT_SECURITY": "strict-transport-security", + "HTTP2_HEADER_TRANSFER_ENCODING": "transfer-encoding", + "HTTP2_HEADER_TE": "te", + "HTTP2_HEADER_UPGRADE_INSECURE_REQUESTS": "upgrade-insecure-requests", + "HTTP2_HEADER_UPGRADE": "upgrade", + "HTTP2_HEADER_USER_AGENT": "user-agent", + "HTTP2_HEADER_VARY": "vary", + "HTTP2_HEADER_X_CONTENT_TYPE_OPTIONS": "x-content-type-options", + "HTTP2_HEADER_X_FRAME_OPTIONS": "x-frame-options", + "HTTP2_HEADER_KEEP_ALIVE": "keep-alive", + "HTTP2_HEADER_PROXY_CONNECTION": "proxy-connection", + "HTTP2_HEADER_X_XSS_PROTECTION": "x-xss-protection", + "HTTP2_HEADER_ALT_SVC": "alt-svc", + "HTTP2_HEADER_CONTENT_SECURITY_POLICY": "content-security-policy", + "HTTP2_HEADER_EARLY_DATA": "early-data", + "HTTP2_HEADER_EXPECT_CT": "expect-ct", + "HTTP2_HEADER_ORIGIN": "origin", + "HTTP2_HEADER_PURPOSE": "purpose", + "HTTP2_HEADER_TIMING_ALLOW_ORIGIN": "timing-allow-origin", + "HTTP2_HEADER_X_FORWARDED_FOR": "x-forwarded-for", + "HTTP2_HEADER_PRIORITY": "priority", + "HTTP2_HEADER_ACCEPT_CHARSET": "accept-charset", + "HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE": "access-control-max-age", + "HTTP2_HEADER_ALLOW": "allow", + "HTTP2_HEADER_CONTENT_LANGUAGE": "content-language", + "HTTP2_HEADER_CONTENT_LOCATION": "content-location", + "HTTP2_HEADER_CONTENT_MD5": "content-md5", + "HTTP2_HEADER_CONTENT_RANGE": "content-range", + "HTTP2_HEADER_DNT": "dnt", + "HTTP2_HEADER_EXPECT": "expect", + "HTTP2_HEADER_EXPIRES": "expires", + "HTTP2_HEADER_FROM": "from", + "HTTP2_HEADER_IF_MATCH": "if-match", + "HTTP2_HEADER_IF_UNMODIFIED_SINCE": "if-unmodified-since", + "HTTP2_HEADER_MAX_FORWARDS": "max-forwards", + "HTTP2_HEADER_PREFER": "prefer", + "HTTP2_HEADER_PROXY_AUTHENTICATE": "proxy-authenticate", + "HTTP2_HEADER_PROXY_AUTHORIZATION": "proxy-authorization", + "HTTP2_HEADER_REFRESH": "refresh", + "HTTP2_HEADER_RETRY_AFTER": "retry-after", + "HTTP2_HEADER_TRAILER": "trailer", + "HTTP2_HEADER_TK": "tk", + "HTTP2_HEADER_VIA": "via", + "HTTP2_HEADER_WARNING": "warning", + "HTTP2_HEADER_WWW_AUTHENTICATE": "www-authenticate", + "HTTP2_HEADER_HTTP2_SETTINGS": "http2-settings", + "HTTP2_METHOD_ACL": "ACL", + "HTTP2_METHOD_BASELINE_CONTROL": "BASELINE-CONTROL", + "HTTP2_METHOD_BIND": "BIND", + "HTTP2_METHOD_CHECKIN": "CHECKIN", + "HTTP2_METHOD_CHECKOUT": "CHECKOUT", + "HTTP2_METHOD_CONNECT": "CONNECT", + "HTTP2_METHOD_COPY": "COPY", + "HTTP2_METHOD_DELETE": "DELETE", + "HTTP2_METHOD_GET": "GET", + "HTTP2_METHOD_HEAD": "HEAD", + "HTTP2_METHOD_LABEL": "LABEL", + "HTTP2_METHOD_LINK": "LINK", + "HTTP2_METHOD_LOCK": "LOCK", + "HTTP2_METHOD_MERGE": "MERGE", + "HTTP2_METHOD_MKACTIVITY": "MKACTIVITY", + "HTTP2_METHOD_MKCALENDAR": "MKCALENDAR", + "HTTP2_METHOD_MKCOL": "MKCOL", + "HTTP2_METHOD_MKREDIRECTREF": "MKREDIRECTREF", + "HTTP2_METHOD_MKWORKSPACE": "MKWORKSPACE", + "HTTP2_METHOD_MOVE": "MOVE", + "HTTP2_METHOD_OPTIONS": "OPTIONS", + "HTTP2_METHOD_ORDERPATCH": "ORDERPATCH", + "HTTP2_METHOD_PATCH": "PATCH", + "HTTP2_METHOD_POST": "POST", + "HTTP2_METHOD_PRI": "PRI", + "HTTP2_METHOD_PROPFIND": "PROPFIND", + "HTTP2_METHOD_PROPPATCH": "PROPPATCH", + "HTTP2_METHOD_PUT": "PUT", + "HTTP2_METHOD_REBIND": "REBIND", + "HTTP2_METHOD_REPORT": "REPORT", + "HTTP2_METHOD_SEARCH": "SEARCH", + "HTTP2_METHOD_TRACE": "TRACE", + "HTTP2_METHOD_UNBIND": "UNBIND", + "HTTP2_METHOD_UNCHECKOUT": "UNCHECKOUT", + "HTTP2_METHOD_UNLINK": "UNLINK", + "HTTP2_METHOD_UNLOCK": "UNLOCK", + "HTTP2_METHOD_UPDATE": "UPDATE", + "HTTP2_METHOD_UPDATEREDIRECTREF": "UPDATEREDIRECTREF", + "HTTP2_METHOD_VERSION_CONTROL": "VERSION-CONTROL", + "HTTP_STATUS_CONTINUE": 100, + "HTTP_STATUS_SWITCHING_PROTOCOLS": 101, + "HTTP_STATUS_PROCESSING": 102, + "HTTP_STATUS_EARLY_HINTS": 103, + "HTTP_STATUS_OK": 200, + "HTTP_STATUS_CREATED": 201, + "HTTP_STATUS_ACCEPTED": 202, + "HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION": 203, + "HTTP_STATUS_NO_CONTENT": 204, + "HTTP_STATUS_RESET_CONTENT": 205, + "HTTP_STATUS_PARTIAL_CONTENT": 206, + "HTTP_STATUS_MULTI_STATUS": 207, + "HTTP_STATUS_ALREADY_REPORTED": 208, + "HTTP_STATUS_IM_USED": 226, + "HTTP_STATUS_MULTIPLE_CHOICES": 300, + "HTTP_STATUS_MOVED_PERMANENTLY": 301, + "HTTP_STATUS_FOUND": 302, + "HTTP_STATUS_SEE_OTHER": 303, + "HTTP_STATUS_NOT_MODIFIED": 304, + "HTTP_STATUS_USE_PROXY": 305, + "HTTP_STATUS_TEMPORARY_REDIRECT": 307, + "HTTP_STATUS_PERMANENT_REDIRECT": 308, + "HTTP_STATUS_BAD_REQUEST": 400, + "HTTP_STATUS_UNAUTHORIZED": 401, + "HTTP_STATUS_PAYMENT_REQUIRED": 402, + "HTTP_STATUS_FORBIDDEN": 403, + "HTTP_STATUS_NOT_FOUND": 404, + "HTTP_STATUS_METHOD_NOT_ALLOWED": 405, + "HTTP_STATUS_NOT_ACCEPTABLE": 406, + "HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED": 407, + "HTTP_STATUS_REQUEST_TIMEOUT": 408, + "HTTP_STATUS_CONFLICT": 409, + "HTTP_STATUS_GONE": 410, + "HTTP_STATUS_LENGTH_REQUIRED": 411, + "HTTP_STATUS_PRECONDITION_FAILED": 412, + "HTTP_STATUS_PAYLOAD_TOO_LARGE": 413, + "HTTP_STATUS_URI_TOO_LONG": 414, + "HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE": 415, + "HTTP_STATUS_RANGE_NOT_SATISFIABLE": 416, + "HTTP_STATUS_EXPECTATION_FAILED": 417, + "HTTP_STATUS_TEAPOT": 418, + "HTTP_STATUS_MISDIRECTED_REQUEST": 421, + "HTTP_STATUS_UNPROCESSABLE_ENTITY": 422, + "HTTP_STATUS_LOCKED": 423, + "HTTP_STATUS_FAILED_DEPENDENCY": 424, + "HTTP_STATUS_TOO_EARLY": 425, + "HTTP_STATUS_UPGRADE_REQUIRED": 426, + "HTTP_STATUS_PRECONDITION_REQUIRED": 428, + "HTTP_STATUS_TOO_MANY_REQUESTS": 429, + "HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE": 431, + "HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS": 451, + "HTTP_STATUS_INTERNAL_SERVER_ERROR": 500, + "HTTP_STATUS_NOT_IMPLEMENTED": 501, + "HTTP_STATUS_BAD_GATEWAY": 502, + "HTTP_STATUS_SERVICE_UNAVAILABLE": 503, + "HTTP_STATUS_GATEWAY_TIMEOUT": 504, + "HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED": 505, + "HTTP_STATUS_VARIANT_ALSO_NEGOTIATES": 506, + "HTTP_STATUS_INSUFFICIENT_STORAGE": 507, + "HTTP_STATUS_LOOP_DETECTED": 508, + "HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED": 509, + "HTTP_STATUS_NOT_EXTENDED": 510, + "HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED": 511, + }); + }); + it("getDefaultSettings", () => { + const settings = http2.getDefaultSettings(); expect(settings).toEqual({ + enableConnectProtocol: false, headerTableSize: 4096, enablePush: false, - maxConcurrentStreams: 4294967295, initialWindowSize: 65535, maxFrameSize: 16384, + maxConcurrentStreams: 4294967295, maxHeaderListSize: 65535, maxHeaderSize: 65535, + }); + }); + it("getPackedSettings/getUnpackedSettings", () => { + const settings = { + headerTableSize: 1, + enablePush: false, + initialWindowSize: 2, + maxFrameSize: 32768, + maxConcurrentStreams: 4, + maxHeaderListSize: 5, + maxHeaderSize: 5, enableConnectProtocol: false, - }); - } finally { - session.close(); - } - }); - it("should be able to mutiplex POST requests", async () => { - const results = await doMultiplexHttp2Request(HTTPS_SERVER, [ - { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 1 }) }, - { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 2 }) }, - { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 3 }) }, - { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 4 }) }, - { headers: { ":path": "/post", ":method": "POST" }, payload: JSON.stringify({ "request": 5 }) }, - ]); - expect(results.length).toBe(5); - for (let i = 0; i < results.length; i++) { - let parsed; - expect(() => (parsed = JSON.parse(results[i].data))).not.toThrow(); - expect(parsed.url).toBe(`${HTTPS_SERVER}/post`); - expect([1, 2, 3, 4, 5]).toContain(parsed.json?.request); - } - }); - it("constants", () => { - expect(http2.constants).toEqual({ - "NGHTTP2_ERR_FRAME_SIZE_ERROR": -522, - "NGHTTP2_SESSION_SERVER": 0, - "NGHTTP2_SESSION_CLIENT": 1, - "NGHTTP2_STREAM_STATE_IDLE": 1, - "NGHTTP2_STREAM_STATE_OPEN": 2, - "NGHTTP2_STREAM_STATE_RESERVED_LOCAL": 3, - "NGHTTP2_STREAM_STATE_RESERVED_REMOTE": 4, - "NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL": 5, - "NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE": 6, - "NGHTTP2_STREAM_STATE_CLOSED": 7, - "NGHTTP2_FLAG_NONE": 0, - "NGHTTP2_FLAG_END_STREAM": 1, - "NGHTTP2_FLAG_END_HEADERS": 4, - "NGHTTP2_FLAG_ACK": 1, - "NGHTTP2_FLAG_PADDED": 8, - "NGHTTP2_FLAG_PRIORITY": 32, - "DEFAULT_SETTINGS_HEADER_TABLE_SIZE": 4096, - "DEFAULT_SETTINGS_ENABLE_PUSH": 1, - "DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS": 4294967295, - "DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE": 65535, - "DEFAULT_SETTINGS_MAX_FRAME_SIZE": 16384, - "DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE": 65535, - "DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL": 0, - "MAX_MAX_FRAME_SIZE": 16777215, - "MIN_MAX_FRAME_SIZE": 16384, - "MAX_INITIAL_WINDOW_SIZE": 2147483647, - "NGHTTP2_SETTINGS_HEADER_TABLE_SIZE": 1, - "NGHTTP2_SETTINGS_ENABLE_PUSH": 2, - "NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS": 3, - "NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE": 4, - "NGHTTP2_SETTINGS_MAX_FRAME_SIZE": 5, - "NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE": 6, - "NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL": 8, - "PADDING_STRATEGY_NONE": 0, - "PADDING_STRATEGY_ALIGNED": 1, - "PADDING_STRATEGY_MAX": 2, - "PADDING_STRATEGY_CALLBACK": 1, - "NGHTTP2_NO_ERROR": 0, - "NGHTTP2_PROTOCOL_ERROR": 1, - "NGHTTP2_INTERNAL_ERROR": 2, - "NGHTTP2_FLOW_CONTROL_ERROR": 3, - "NGHTTP2_SETTINGS_TIMEOUT": 4, - "NGHTTP2_STREAM_CLOSED": 5, - "NGHTTP2_FRAME_SIZE_ERROR": 6, - "NGHTTP2_REFUSED_STREAM": 7, - "NGHTTP2_CANCEL": 8, - "NGHTTP2_COMPRESSION_ERROR": 9, - "NGHTTP2_CONNECT_ERROR": 10, - "NGHTTP2_ENHANCE_YOUR_CALM": 11, - "NGHTTP2_INADEQUATE_SECURITY": 12, - "NGHTTP2_HTTP_1_1_REQUIRED": 13, - "NGHTTP2_DEFAULT_WEIGHT": 16, - "HTTP2_HEADER_STATUS": ":status", - "HTTP2_HEADER_METHOD": ":method", - "HTTP2_HEADER_AUTHORITY": ":authority", - "HTTP2_HEADER_SCHEME": ":scheme", - "HTTP2_HEADER_PATH": ":path", - "HTTP2_HEADER_PROTOCOL": ":protocol", - "HTTP2_HEADER_ACCEPT_ENCODING": "accept-encoding", - "HTTP2_HEADER_ACCEPT_LANGUAGE": "accept-language", - "HTTP2_HEADER_ACCEPT_RANGES": "accept-ranges", - "HTTP2_HEADER_ACCEPT": "accept", - "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS": "access-control-allow-credentials", - "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS": "access-control-allow-headers", - "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS": "access-control-allow-methods", - "HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN": "access-control-allow-origin", - "HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS": "access-control-expose-headers", - "HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS": "access-control-request-headers", - "HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD": "access-control-request-method", - "HTTP2_HEADER_AGE": "age", - "HTTP2_HEADER_AUTHORIZATION": "authorization", - "HTTP2_HEADER_CACHE_CONTROL": "cache-control", - "HTTP2_HEADER_CONNECTION": "connection", - "HTTP2_HEADER_CONTENT_DISPOSITION": "content-disposition", - "HTTP2_HEADER_CONTENT_ENCODING": "content-encoding", - "HTTP2_HEADER_CONTENT_LENGTH": "content-length", - "HTTP2_HEADER_CONTENT_TYPE": "content-type", - "HTTP2_HEADER_COOKIE": "cookie", - "HTTP2_HEADER_DATE": "date", - "HTTP2_HEADER_ETAG": "etag", - "HTTP2_HEADER_FORWARDED": "forwarded", - "HTTP2_HEADER_HOST": "host", - "HTTP2_HEADER_IF_MODIFIED_SINCE": "if-modified-since", - "HTTP2_HEADER_IF_NONE_MATCH": "if-none-match", - "HTTP2_HEADER_IF_RANGE": "if-range", - "HTTP2_HEADER_LAST_MODIFIED": "last-modified", - "HTTP2_HEADER_LINK": "link", - "HTTP2_HEADER_LOCATION": "location", - "HTTP2_HEADER_RANGE": "range", - "HTTP2_HEADER_REFERER": "referer", - "HTTP2_HEADER_SERVER": "server", - "HTTP2_HEADER_SET_COOKIE": "set-cookie", - "HTTP2_HEADER_STRICT_TRANSPORT_SECURITY": "strict-transport-security", - "HTTP2_HEADER_TRANSFER_ENCODING": "transfer-encoding", - "HTTP2_HEADER_TE": "te", - "HTTP2_HEADER_UPGRADE_INSECURE_REQUESTS": "upgrade-insecure-requests", - "HTTP2_HEADER_UPGRADE": "upgrade", - "HTTP2_HEADER_USER_AGENT": "user-agent", - "HTTP2_HEADER_VARY": "vary", - "HTTP2_HEADER_X_CONTENT_TYPE_OPTIONS": "x-content-type-options", - "HTTP2_HEADER_X_FRAME_OPTIONS": "x-frame-options", - "HTTP2_HEADER_KEEP_ALIVE": "keep-alive", - "HTTP2_HEADER_PROXY_CONNECTION": "proxy-connection", - "HTTP2_HEADER_X_XSS_PROTECTION": "x-xss-protection", - "HTTP2_HEADER_ALT_SVC": "alt-svc", - "HTTP2_HEADER_CONTENT_SECURITY_POLICY": "content-security-policy", - "HTTP2_HEADER_EARLY_DATA": "early-data", - "HTTP2_HEADER_EXPECT_CT": "expect-ct", - "HTTP2_HEADER_ORIGIN": "origin", - "HTTP2_HEADER_PURPOSE": "purpose", - "HTTP2_HEADER_TIMING_ALLOW_ORIGIN": "timing-allow-origin", - "HTTP2_HEADER_X_FORWARDED_FOR": "x-forwarded-for", - "HTTP2_HEADER_PRIORITY": "priority", - "HTTP2_HEADER_ACCEPT_CHARSET": "accept-charset", - "HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE": "access-control-max-age", - "HTTP2_HEADER_ALLOW": "allow", - "HTTP2_HEADER_CONTENT_LANGUAGE": "content-language", - "HTTP2_HEADER_CONTENT_LOCATION": "content-location", - "HTTP2_HEADER_CONTENT_MD5": "content-md5", - "HTTP2_HEADER_CONTENT_RANGE": "content-range", - "HTTP2_HEADER_DNT": "dnt", - "HTTP2_HEADER_EXPECT": "expect", - "HTTP2_HEADER_EXPIRES": "expires", - "HTTP2_HEADER_FROM": "from", - "HTTP2_HEADER_IF_MATCH": "if-match", - "HTTP2_HEADER_IF_UNMODIFIED_SINCE": "if-unmodified-since", - "HTTP2_HEADER_MAX_FORWARDS": "max-forwards", - "HTTP2_HEADER_PREFER": "prefer", - "HTTP2_HEADER_PROXY_AUTHENTICATE": "proxy-authenticate", - "HTTP2_HEADER_PROXY_AUTHORIZATION": "proxy-authorization", - "HTTP2_HEADER_REFRESH": "refresh", - "HTTP2_HEADER_RETRY_AFTER": "retry-after", - "HTTP2_HEADER_TRAILER": "trailer", - "HTTP2_HEADER_TK": "tk", - "HTTP2_HEADER_VIA": "via", - "HTTP2_HEADER_WARNING": "warning", - "HTTP2_HEADER_WWW_AUTHENTICATE": "www-authenticate", - "HTTP2_HEADER_HTTP2_SETTINGS": "http2-settings", - "HTTP2_METHOD_ACL": "ACL", - "HTTP2_METHOD_BASELINE_CONTROL": "BASELINE-CONTROL", - "HTTP2_METHOD_BIND": "BIND", - "HTTP2_METHOD_CHECKIN": "CHECKIN", - "HTTP2_METHOD_CHECKOUT": "CHECKOUT", - "HTTP2_METHOD_CONNECT": "CONNECT", - "HTTP2_METHOD_COPY": "COPY", - "HTTP2_METHOD_DELETE": "DELETE", - "HTTP2_METHOD_GET": "GET", - "HTTP2_METHOD_HEAD": "HEAD", - "HTTP2_METHOD_LABEL": "LABEL", - "HTTP2_METHOD_LINK": "LINK", - "HTTP2_METHOD_LOCK": "LOCK", - "HTTP2_METHOD_MERGE": "MERGE", - "HTTP2_METHOD_MKACTIVITY": "MKACTIVITY", - "HTTP2_METHOD_MKCALENDAR": "MKCALENDAR", - "HTTP2_METHOD_MKCOL": "MKCOL", - "HTTP2_METHOD_MKREDIRECTREF": "MKREDIRECTREF", - "HTTP2_METHOD_MKWORKSPACE": "MKWORKSPACE", - "HTTP2_METHOD_MOVE": "MOVE", - "HTTP2_METHOD_OPTIONS": "OPTIONS", - "HTTP2_METHOD_ORDERPATCH": "ORDERPATCH", - "HTTP2_METHOD_PATCH": "PATCH", - "HTTP2_METHOD_POST": "POST", - "HTTP2_METHOD_PRI": "PRI", - "HTTP2_METHOD_PROPFIND": "PROPFIND", - "HTTP2_METHOD_PROPPATCH": "PROPPATCH", - "HTTP2_METHOD_PUT": "PUT", - "HTTP2_METHOD_REBIND": "REBIND", - "HTTP2_METHOD_REPORT": "REPORT", - "HTTP2_METHOD_SEARCH": "SEARCH", - "HTTP2_METHOD_TRACE": "TRACE", - "HTTP2_METHOD_UNBIND": "UNBIND", - "HTTP2_METHOD_UNCHECKOUT": "UNCHECKOUT", - "HTTP2_METHOD_UNLINK": "UNLINK", - "HTTP2_METHOD_UNLOCK": "UNLOCK", - "HTTP2_METHOD_UPDATE": "UPDATE", - "HTTP2_METHOD_UPDATEREDIRECTREF": "UPDATEREDIRECTREF", - "HTTP2_METHOD_VERSION_CONTROL": "VERSION-CONTROL", - "HTTP_STATUS_CONTINUE": 100, - "HTTP_STATUS_SWITCHING_PROTOCOLS": 101, - "HTTP_STATUS_PROCESSING": 102, - "HTTP_STATUS_EARLY_HINTS": 103, - "HTTP_STATUS_OK": 200, - "HTTP_STATUS_CREATED": 201, - "HTTP_STATUS_ACCEPTED": 202, - "HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION": 203, - "HTTP_STATUS_NO_CONTENT": 204, - "HTTP_STATUS_RESET_CONTENT": 205, - "HTTP_STATUS_PARTIAL_CONTENT": 206, - "HTTP_STATUS_MULTI_STATUS": 207, - "HTTP_STATUS_ALREADY_REPORTED": 208, - "HTTP_STATUS_IM_USED": 226, - "HTTP_STATUS_MULTIPLE_CHOICES": 300, - "HTTP_STATUS_MOVED_PERMANENTLY": 301, - "HTTP_STATUS_FOUND": 302, - "HTTP_STATUS_SEE_OTHER": 303, - "HTTP_STATUS_NOT_MODIFIED": 304, - "HTTP_STATUS_USE_PROXY": 305, - "HTTP_STATUS_TEMPORARY_REDIRECT": 307, - "HTTP_STATUS_PERMANENT_REDIRECT": 308, - "HTTP_STATUS_BAD_REQUEST": 400, - "HTTP_STATUS_UNAUTHORIZED": 401, - "HTTP_STATUS_PAYMENT_REQUIRED": 402, - "HTTP_STATUS_FORBIDDEN": 403, - "HTTP_STATUS_NOT_FOUND": 404, - "HTTP_STATUS_METHOD_NOT_ALLOWED": 405, - "HTTP_STATUS_NOT_ACCEPTABLE": 406, - "HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED": 407, - "HTTP_STATUS_REQUEST_TIMEOUT": 408, - "HTTP_STATUS_CONFLICT": 409, - "HTTP_STATUS_GONE": 410, - "HTTP_STATUS_LENGTH_REQUIRED": 411, - "HTTP_STATUS_PRECONDITION_FAILED": 412, - "HTTP_STATUS_PAYLOAD_TOO_LARGE": 413, - "HTTP_STATUS_URI_TOO_LONG": 414, - "HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE": 415, - "HTTP_STATUS_RANGE_NOT_SATISFIABLE": 416, - "HTTP_STATUS_EXPECTATION_FAILED": 417, - "HTTP_STATUS_TEAPOT": 418, - "HTTP_STATUS_MISDIRECTED_REQUEST": 421, - "HTTP_STATUS_UNPROCESSABLE_ENTITY": 422, - "HTTP_STATUS_LOCKED": 423, - "HTTP_STATUS_FAILED_DEPENDENCY": 424, - "HTTP_STATUS_TOO_EARLY": 425, - "HTTP_STATUS_UPGRADE_REQUIRED": 426, - "HTTP_STATUS_PRECONDITION_REQUIRED": 428, - "HTTP_STATUS_TOO_MANY_REQUESTS": 429, - "HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE": 431, - "HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS": 451, - "HTTP_STATUS_INTERNAL_SERVER_ERROR": 500, - "HTTP_STATUS_NOT_IMPLEMENTED": 501, - "HTTP_STATUS_BAD_GATEWAY": 502, - "HTTP_STATUS_SERVICE_UNAVAILABLE": 503, - "HTTP_STATUS_GATEWAY_TIMEOUT": 504, - "HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED": 505, - "HTTP_STATUS_VARIANT_ALSO_NEGOTIATES": 506, - "HTTP_STATUS_INSUFFICIENT_STORAGE": 507, - "HTTP_STATUS_LOOP_DETECTED": 508, - "HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED": 509, - "HTTP_STATUS_NOT_EXTENDED": 510, - "HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED": 511, + }; + const buffer = http2.getPackedSettings(settings); + expect(buffer.byteLength).toBe(36); + expect(http2.getUnpackedSettings(buffer)).toEqual(settings); }); - }); - it("getDefaultSettings", () => { - const settings = http2.getDefaultSettings(); - expect(settings).toEqual({ - enableConnectProtocol: false, - headerTableSize: 4096, - enablePush: false, - initialWindowSize: 65535, - maxFrameSize: 16384, - maxConcurrentStreams: 4294967295, - maxHeaderListSize: 65535, - maxHeaderSize: 65535, + it("getUnpackedSettings should throw if buffer is too small", () => { + const buffer = new ArrayBuffer(1); + expect(() => http2.getUnpackedSettings(buffer)).toThrow( + /Expected buf to be a Buffer of at least 6 bytes and a multiple of 6 bytes/, + ); }); - }); - it("getPackedSettings/getUnpackedSettings", () => { - const settings = { - headerTableSize: 1, - enablePush: false, - initialWindowSize: 2, - maxFrameSize: 32768, - maxConcurrentStreams: 4, - maxHeaderListSize: 5, - maxHeaderSize: 5, - enableConnectProtocol: false, - }; - const buffer = http2.getPackedSettings(settings); - expect(buffer.byteLength).toBe(36); - expect(http2.getUnpackedSettings(buffer)).toEqual(settings); - }); - it("getUnpackedSettings should throw if buffer is too small", () => { - const buffer = new ArrayBuffer(1); - expect(() => http2.getUnpackedSettings(buffer)).toThrow( - /Expected buf to be a Buffer of at least 6 bytes and a multiple of 6 bytes/, - ); - }); - it("getUnpackedSettings should throw if buffer is not a multiple of 6 bytes", () => { - const buffer = new ArrayBuffer(7); - expect(() => http2.getUnpackedSettings(buffer)).toThrow( - /Expected buf to be a Buffer of at least 6 bytes and a multiple of 6 bytes/, - ); - }); - it("getUnpackedSettings should throw if buffer is not a buffer", () => { - const buffer = {}; - expect(() => http2.getUnpackedSettings(buffer)).toThrow(/Expected buf to be a Buffer/); - }); - it("headers cannot be bigger than 65536 bytes", async () => { - try { - await doHttp2Request(HTTPS_SERVER, { ":path": "/", "test-header": "A".repeat(90000) }); - expect("unreachable").toBe(true); - } catch (err) { - expect(err.code).toBe("ERR_HTTP2_STREAM_ERROR"); - expect(err.message).toBe("Stream closed with error code NGHTTP2_COMPRESSION_ERROR"); - } - }); - it("should be destroyed after close", async () => { - const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); - const client = http2.connect(`${HTTPS_SERVER}/get`, TLS_OPTIONS); - client.on("error", promiseReject); - client.on("close", resolve); - function reject(err) { - promiseReject(err); - client.close(); - } - const req = client.request({ - ":path": "/get", + it("getUnpackedSettings should throw if buffer is not a multiple of 6 bytes", () => { + const buffer = new ArrayBuffer(7); + expect(() => http2.getUnpackedSettings(buffer)).toThrow( + /Expected buf to be a Buffer of at least 6 bytes and a multiple of 6 bytes/, + ); }); - req.resume(); - req.on("error", reject); - req.on("end", () => { - client.close(); + it("getUnpackedSettings should throw if buffer is not a buffer", () => { + const buffer = {}; + expect(() => http2.getUnpackedSettings(buffer)).toThrow(/Expected buf to be a Buffer/); }); - req.end(); - await promise; - expect(client.destroyed).toBe(true); - }); - it("should be destroyed after destroy", async () => { - const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); - const client = http2.connect(`${HTTPS_SERVER}/get`, TLS_OPTIONS); - client.on("error", promiseReject); - client.on("close", resolve); - function reject(err) { - promiseReject(err); - client.destroy(); - } - const req = client.request({ - ":path": "/get", - }); - req.on("error", reject); - req.resume(); - req.on("end", () => { - client.destroy(); - }); - req.end(); - await promise; - expect(client.destroyed).toBe(true); - }); - it("should fail to connect over HTTP/1.1", async () => { - const tls = TLS_CERT; - using server = Bun.serve({ - port: 0, - hostname: "127.0.0.1", - tls: { - ...tls, - ca: TLS_CERT.ca, - }, - fetch() { - return new Response("hello"); - }, - }); - const url = `https://127.0.0.1:${server.port}`; - try { - await doHttp2Request(url, { ":path": "/" }, null, TLS_OPTIONS); - expect("unreachable").toBe(true); - } catch (err) { - expect(err.code).toBe("ERR_HTTP2_ERROR"); - } - }); - it("works with Duplex", async () => { - class JSSocket extends Duplex { - constructor(socket) { - super({ emitClose: true }); - socket.on("close", () => this.destroy()); - socket.on("data", data => this.push(data)); - this.socket = socket; - } - _write(data, encoding, callback) { - this.socket.write(data, encoding, callback); - } - _read(size) {} - _final(cb) { - cb(); - } - } - const { promise, resolve, reject } = Promise.withResolvers(); - const socket = tls - .connect( - { - rejectUnauthorized: false, - host: new URL(HTTPS_SERVER).hostname, - port: new URL(HTTPS_SERVER).port, - ALPNProtocols: ["h2"], - ...TLS_OPTIONS, - }, - () => { - doHttp2Request(`${HTTPS_SERVER}/get`, { ":path": "/get" }, null, { - createConnection: () => { - return new JSSocket(socket); - }, - }).then(resolve, reject); - }, - ) - .on("error", reject); - const result = await promise; - let parsed; - expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); - expect(parsed.url).toBe(`${HTTPS_SERVER}/get`); - socket.destroy(); - }); - it("close callback", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(`${HTTPS_SERVER}/get`, TLS_OPTIONS); - client.on("error", reject); - client.close(resolve); - await promise; - expect(client.destroyed).toBe(true); - }); - it("is possible to abort request", async () => { - const abortController = new AbortController(); - const promise = doHttp2Request(`${HTTPS_SERVER}/get`, { ":path": "/get" }, null, null, { - signal: abortController.signal, - }); - abortController.abort(); - try { - await promise; - expect("unreachable").toBe(true); - } catch (err) { - expect(err.code).toBe("ABORT_ERR"); - } - }); - it("aborted event should work with abortController", async () => { - const abortController = new AbortController(); - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - const req = client.request({ ":path": "/post", ":method": "POST" }, { signal: abortController.signal }); - req.on("aborted", resolve); - req.on("error", err => { - if (err.code !== "ABORT_ERR") { - reject(err); - } - }); - req.on("end", () => { - reject(); - client.close(); - }); - abortController.abort(); - const result = await promise; - expect(result).toBeUndefined(); - expect(req.aborted).toBeTrue(); - expect(req.rstCode).toBe(http2.constants.NGHTTP2_CANCEL); - }); - - it("aborted event should work with aborted signal", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - const req = client.request({ ":path": "/post", ":method": "POST" }, { signal: AbortSignal.abort() }); - req.on("aborted", reject); // will not be emited because we could not start the request at all - req.on("error", err => { - if (err.name !== "AbortError") { - reject(err); - } else { - resolve(); - } - }); - req.on("end", () => { - client.close(); - }); - const result = await promise; - expect(result).toBeUndefined(); - expect(req.rstCode).toBe(http2.constants.NGHTTP2_CANCEL); - expect(req.aborted).toBeTrue(); // will be true in this case - }); - - it("state should work", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - const req = client.request({ ":path": "/", "test-header": "test-value" }); - { - const state = req.state; - expect(typeof state).toBe("object"); - expect(typeof state.state).toBe("number"); - expect(typeof state.weight).toBe("number"); - expect(typeof state.sumDependencyWeight).toBe("number"); - expect(typeof state.localClose).toBe("number"); - expect(typeof state.remoteClose).toBe("number"); - expect(typeof state.localWindowSize).toBe("number"); - } - // Test Session State. - { - const state = client.state; - expect(typeof state).toBe("object"); - expect(typeof state.effectiveLocalWindowSize).toBe("number"); - expect(typeof state.effectiveRecvDataLength).toBe("number"); - expect(typeof state.nextStreamID).toBe("number"); - expect(typeof state.localWindowSize).toBe("number"); - expect(typeof state.lastProcStreamID).toBe("number"); - expect(typeof state.remoteWindowSize).toBe("number"); - expect(typeof state.outboundQueueSize).toBe("number"); - expect(typeof state.deflateDynamicTableSize).toBe("number"); - expect(typeof state.inflateDynamicTableSize).toBe("number"); - } - let response_headers = null; - req.on("response", (headers, flags) => { - response_headers = headers; - }); - req.resume(); - req.on("end", () => { - resolve(); - client.close(); - }); - await promise; - expect(response_headers[":status"]).toBe(200); - }); - it("settings and properties should work", async () => { - const assertSettings = settings => { - expect(settings).toBeDefined(); - expect(typeof settings).toBe("object"); - expect(typeof settings.headerTableSize).toBe("number"); - expect(typeof settings.enablePush).toBe("boolean"); - expect(typeof settings.initialWindowSize).toBe("number"); - expect(typeof settings.maxFrameSize).toBe("number"); - expect(typeof settings.maxConcurrentStreams).toBe("number"); - expect(typeof settings.maxHeaderListSize).toBe("number"); - expect(typeof settings.maxHeaderSize).toBe("number"); - }; - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect("https://www.example.com"); - client.on("error", reject); - expect(client.connecting).toBeTrue(); - expect(client.alpnProtocol).toBeUndefined(); - expect(client.encrypted).toBeTrue(); - expect(client.closed).toBeFalse(); - expect(client.destroyed).toBeFalse(); - expect(client.originSet.length).toBe(1); - expect(client.pendingSettingsAck).toBeTrue(); - assertSettings(client.localSettings); - expect(client.remoteSettings).toBeNull(); - const headers = { ":path": "/" }; - const req = client.request(headers); - expect(req.closed).toBeFalse(); - expect(req.destroyed).toBeFalse(); - // we always asign a stream id to the request - expect(req.pending).toBeFalse(); - expect(typeof req.id).toBe("number"); - expect(req.session).toBeDefined(); - expect(req.sentHeaders).toEqual({ - ":authority": "www.example.com", - ":method": "GET", - ":path": "/", - ":scheme": "https", - }); - expect(req.sentTrailers).toBeUndefined(); - expect(req.sentInfoHeaders.length).toBe(0); - expect(req.scheme).toBe("https"); - let response_headers = null; - req.on("response", (headers, flags) => { - response_headers = headers; - }); - req.resume(); - req.on("end", () => { - resolve(); - }); - await promise; - expect(response_headers[":status"]).toBe(200); - const settings = client.remoteSettings; - const localSettings = client.localSettings; - assertSettings(settings); - assertSettings(localSettings); - expect(settings).toEqual(client.remoteSettings); - expect(localSettings).toEqual(client.localSettings); - client.destroy(); - expect(client.connecting).toBeFalse(); - expect(client.alpnProtocol).toBe("h2"); - expect(client.pendingSettingsAck).toBeFalse(); - expect(client.destroyed).toBeTrue(); - expect(client.closed).toBeTrue(); - expect(req.closed).toBeTrue(); - expect(req.destroyed).toBeTrue(); - expect(req.rstCode).toBe(http2.constants.NGHTTP2_NO_ERROR); - }); - it("ping events should work", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - client.on("connect", () => { - client.ping(Buffer.from("12345678"), (err, duration, payload) => { - if (err) { - reject(err); - } else { - resolve({ duration, payload }); - } - client.close(); - }); - }); - let received_ping; - client.on("ping", payload => { - received_ping = payload; - }); - const result = await promise; - expect(typeof result.duration).toBe("number"); - expect(result.payload).toBeInstanceOf(Buffer); - expect(result.payload.byteLength).toBe(8); - expect(received_ping).toBeInstanceOf(Buffer); - expect(received_ping.byteLength).toBe(8); - expect(received_ping).toEqual(result.payload); - expect(received_ping).toEqual(Buffer.from("12345678")); - }); - it("ping without events should work", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - client.on("connect", () => { - client.ping((err, duration, payload) => { - if (err) { - reject(err); - } else { - resolve({ duration, payload }); - } - client.close(); - }); - }); - let received_ping; - client.on("ping", payload => { - received_ping = payload; - }); - const result = await promise; - expect(typeof result.duration).toBe("number"); - expect(result.payload).toBeInstanceOf(Buffer); - expect(result.payload.byteLength).toBe(8); - expect(received_ping).toBeInstanceOf(Buffer); - expect(received_ping.byteLength).toBe(8); - expect(received_ping).toEqual(result.payload); - }); - it("ping with wrong payload length events should error", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - client.on("connect", () => { - client.ping(Buffer.from("oops"), (err, duration, payload) => { - if (err) { - resolve(err); - } else { - reject("unreachable"); - } - client.close(); - }); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_PING_LENGTH"); - }); - it("ping with wrong payload type events should throw", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - client.on("connect", () => { + it("headers cannot be bigger than 65536 bytes", async () => { try { - client.ping("oops", (err, duration, payload) => { - reject("unreachable"); + await doHttp2Request(HTTPS_SERVER, { ":path": "/", "test-header": "A".repeat(90000) }); + expect("unreachable").toBe(true); + } catch (err) { + expect(err.code).toBe("ERR_HTTP2_STREAM_ERROR"); + expect(err.message).toBe("Stream closed with error code NGHTTP2_COMPRESSION_ERROR"); + } + }); + it("should be destroyed after close", async () => { + const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); + const client = http2.connect(`${HTTPS_SERVER}/get`, TLS_OPTIONS); + client.on("error", promiseReject); + client.on("close", resolve); + function reject(err) { + promiseReject(err); + client.close(); + } + const req = client.request({ + ":path": "/get", + }); + req.resume(); + req.on("error", reject); + req.on("end", () => { + client.close(); + }); + req.end(); + await promise; + expect(client.destroyed).toBe(true); + }); + it("should be destroyed after destroy", async () => { + const { promise, resolve, reject: promiseReject } = Promise.withResolvers(); + const client = http2.connect(`${HTTPS_SERVER}/get`, TLS_OPTIONS); + client.on("error", promiseReject); + client.on("close", resolve); + function reject(err) { + promiseReject(err); + client.destroy(); + } + const req = client.request({ + ":path": "/get", + }); + req.on("error", reject); + req.resume(); + req.on("end", () => { + client.destroy(); + }); + req.end(); + await promise; + expect(client.destroyed).toBe(true); + }); + it("should fail to connect over HTTP/1.1", async () => { + const tls = TLS_CERT; + using server = Bun.serve({ + port: 0, + hostname: "127.0.0.1", + tls: { + ...tls, + ca: TLS_CERT.ca, + }, + fetch() { + return new Response("hello"); + }, + }); + const url = `https://127.0.0.1:${server.port}`; + try { + await doHttp2Request(url, { ":path": "/" }, null, TLS_OPTIONS); + expect("unreachable").toBe(true); + } catch (err) { + expect(err.code).toBe("ERR_HTTP2_ERROR"); + } + }); + it("works with Duplex", async () => { + class JSSocket extends Duplex { + constructor(socket) { + super({ emitClose: true }); + socket.on("close", () => this.destroy()); + socket.on("data", data => this.push(data)); + this.socket = socket; + } + _write(data, encoding, callback) { + this.socket.write(data, encoding, callback); + } + _read(size) {} + _final(cb) { + cb(); + } + } + const { promise, resolve, reject } = Promise.withResolvers(); + const socket = tls + .connect( + { + rejectUnauthorized: false, + host: new URL(HTTPS_SERVER).hostname, + port: new URL(HTTPS_SERVER).port, + ALPNProtocols: ["h2"], + ...TLS_OPTIONS, + }, + () => { + doHttp2Request(`${HTTPS_SERVER}/get`, { ":path": "/get" }, null, { + createConnection: () => { + return new JSSocket(socket); + }, + }).then(resolve, reject); + }, + ) + .on("error", reject); + const result = await promise; + let parsed; + expect(() => (parsed = JSON.parse(result.data))).not.toThrow(); + expect(parsed.url).toBe(`${HTTPS_SERVER}/get`); + socket.destroy(); + }); + it("close callback", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(`${HTTPS_SERVER}/get`, TLS_OPTIONS); + client.on("error", reject); + client.close(resolve); + await promise; + expect(client.destroyed).toBe(true); + }); + it("is possible to abort request", async () => { + const abortController = new AbortController(); + const promise = doHttp2Request(`${HTTPS_SERVER}/get`, { ":path": "/get" }, null, null, { + signal: abortController.signal, + }); + abortController.abort(); + try { + await promise; + expect("unreachable").toBe(true); + } catch (err) { + expect(err.code).toBe("ABORT_ERR"); + } + }); + it("aborted event should work with abortController", async () => { + const abortController = new AbortController(); + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + const req = client.request({ ":path": "/post", ":method": "POST" }, { signal: abortController.signal }); + req.on("aborted", resolve); + req.on("error", err => { + if (err.code !== "ABORT_ERR") { + reject(err); + } + }); + req.on("end", () => { + reject(); + client.close(); + }); + abortController.abort(); + const result = await promise; + expect(result).toBeUndefined(); + expect(req.aborted).toBeTrue(); + expect(req.rstCode).toBe(http2.constants.NGHTTP2_CANCEL); + }); + + it("aborted event should work with aborted signal", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + const req = client.request({ ":path": "/post", ":method": "POST" }, { signal: AbortSignal.abort() }); + req.on("aborted", reject); // will not be emited because we could not start the request at all + req.on("error", err => { + if (err.name !== "AbortError") { + reject(err); + } else { + resolve(); + } + }); + req.on("end", () => { + client.close(); + }); + const result = await promise; + expect(result).toBeUndefined(); + expect(req.rstCode).toBe(http2.constants.NGHTTP2_CANCEL); + expect(req.aborted).toBeTrue(); // will be true in this case + }); + + it("state should work", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + const req = client.request({ ":path": "/", "test-header": "test-value" }); + { + const state = req.state; + expect(typeof state).toBe("object"); + expect(typeof state.state).toBe("number"); + expect(typeof state.weight).toBe("number"); + expect(typeof state.sumDependencyWeight).toBe("number"); + expect(typeof state.localClose).toBe("number"); + expect(typeof state.remoteClose).toBe("number"); + expect(typeof state.localWindowSize).toBe("number"); + } + // Test Session State. + { + const state = client.state; + expect(typeof state).toBe("object"); + expect(typeof state.effectiveLocalWindowSize).toBe("number"); + expect(typeof state.effectiveRecvDataLength).toBe("number"); + expect(typeof state.nextStreamID).toBe("number"); + expect(typeof state.localWindowSize).toBe("number"); + expect(typeof state.lastProcStreamID).toBe("number"); + expect(typeof state.remoteWindowSize).toBe("number"); + expect(typeof state.outboundQueueSize).toBe("number"); + expect(typeof state.deflateDynamicTableSize).toBe("number"); + expect(typeof state.inflateDynamicTableSize).toBe("number"); + } + let response_headers = null; + req.on("response", (headers, flags) => { + response_headers = headers; + }); + req.resume(); + req.on("end", () => { + resolve(); + client.close(); + }); + await promise; + expect(response_headers[":status"]).toBe(200); + }); + it("settings and properties should work", async () => { + const assertSettings = settings => { + expect(settings).toBeDefined(); + expect(typeof settings).toBe("object"); + expect(typeof settings.headerTableSize).toBe("number"); + expect(typeof settings.enablePush).toBe("boolean"); + expect(typeof settings.initialWindowSize).toBe("number"); + expect(typeof settings.maxFrameSize).toBe("number"); + expect(typeof settings.maxConcurrentStreams).toBe("number"); + expect(typeof settings.maxHeaderListSize).toBe("number"); + expect(typeof settings.maxHeaderSize).toBe("number"); + }; + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect("https://www.example.com"); + client.on("error", reject); + expect(client.connecting).toBeTrue(); + expect(client.alpnProtocol).toBeUndefined(); + expect(client.encrypted).toBeTrue(); + expect(client.closed).toBeFalse(); + expect(client.destroyed).toBeFalse(); + expect(client.originSet.length).toBe(1); + expect(client.pendingSettingsAck).toBeTrue(); + assertSettings(client.localSettings); + expect(client.remoteSettings).toBeNull(); + const headers = { ":path": "/" }; + const req = client.request(headers); + expect(req.closed).toBeFalse(); + expect(req.destroyed).toBeFalse(); + // we always asign a stream id to the request + expect(req.pending).toBeFalse(); + expect(typeof req.id).toBe("number"); + expect(req.session).toBeDefined(); + expect(req.sentHeaders).toEqual({ + ":authority": "www.example.com", + ":method": "GET", + ":path": "/", + ":scheme": "https", + }); + expect(req.sentTrailers).toBeUndefined(); + expect(req.sentInfoHeaders.length).toBe(0); + expect(req.scheme).toBe("https"); + let response_headers = null; + req.on("response", (headers, flags) => { + response_headers = headers; + }); + req.resume(); + req.on("end", () => { + resolve(); + }); + await promise; + expect(response_headers[":status"]).toBe(200); + const settings = client.remoteSettings; + const localSettings = client.localSettings; + assertSettings(settings); + assertSettings(localSettings); + expect(settings).toEqual(client.remoteSettings); + expect(localSettings).toEqual(client.localSettings); + client.destroy(); + expect(client.connecting).toBeFalse(); + expect(client.alpnProtocol).toBe("h2"); + expect(client.pendingSettingsAck).toBeFalse(); + expect(client.destroyed).toBeTrue(); + expect(client.closed).toBeTrue(); + expect(req.closed).toBeTrue(); + expect(req.destroyed).toBeTrue(); + expect(req.rstCode).toBe(http2.constants.NGHTTP2_NO_ERROR); + }); + it("ping events should work", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + client.on("connect", () => { + client.ping(Buffer.from("12345678"), (err, duration, payload) => { + if (err) { + reject(err); + } else { + resolve({ duration, payload }); + } client.close(); }); - } catch (err) { - resolve(err); - client.close(); - } - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_INVALID_ARG_TYPE"); - }); - it("stream event should work", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - client.on("stream", stream => { - resolve(stream); - client.close(); - }); - client.request({ ":path": "/" }).end(); - const stream = await promise; - expect(stream).toBeDefined(); - expect(stream.id).toBe(1); - }); - - it("wantTrailers should work", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); - client.on("error", reject); - const headers = { ":path": "/", ":method": "POST", "x-wait-trailer": "true" }; - const req = client.request(headers, { - waitForTrailers: true, - }); - req.setEncoding("utf8"); - let response_headers; - req.on("response", headers => { - response_headers = headers; - }); - let trailers = { "x-trailer": "hello" }; - req.on("wantTrailers", () => { - req.sendTrailers(trailers); - }); - let data = ""; - req.on("data", chunk => { - data += chunk; - client.close(); - }); - req.on("error", reject); - req.on("end", () => { - resolve({ data, headers: response_headers }); - client.close(); - }); - req.end("hello"); - const response = await promise; - let parsed; - expect(() => (parsed = JSON.parse(response.data))).not.toThrow(); - expect(parsed.headers[":method"]).toEqual(headers[":method"]); - expect(parsed.headers[":path"]).toEqual(headers[":path"]); - expect(parsed.headers["x-wait-trailer"]).toEqual(headers["x-wait-trailer"]); - expect(parsed.trailers).toEqual(trailers); - expect(response.headers[":status"]).toBe(200); - expect(response.headers["set-cookie"]).toEqual([ - "a=b", - "c=d; Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly", - "e=f", - ]); - }); - - it.skipIf(!isCI)( - "should not leak memory", - () => { - const { stdout, exitCode } = Bun.spawnSync({ - cmd: [bunExe(), "--smol", "run", path.join(import.meta.dir, "node-http2-memory-leak.js")], - env: { - ...bunEnv, - BUN_JSC_forceRAMSize: (1024 * 1024 * 64).toString("10"), - HTTP2_SERVER_INFO: JSON.stringify(nodeEchoServer_), - HTTP2_SERVER_TLS: JSON.stringify(TLS_OPTIONS), - }, - stderr: "inherit", - stdin: "inherit", - stdout: "inherit", }); - expect(exitCode || 0).toBe(0); - }, - 100000, - ); + let received_ping; + client.on("ping", payload => { + received_ping = payload; + }); + const result = await promise; + expect(typeof result.duration).toBe("number"); + expect(result.payload).toBeInstanceOf(Buffer); + expect(result.payload.byteLength).toBe(8); + expect(received_ping).toBeInstanceOf(Buffer); + expect(received_ping.byteLength).toBe(8); + expect(received_ping).toEqual(result.payload); + expect(received_ping).toEqual(Buffer.from("12345678")); + }); + it("ping without events should work", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + client.on("connect", () => { + client.ping((err, duration, payload) => { + if (err) { + reject(err); + } else { + resolve({ duration, payload }); + } + client.close(); + }); + }); + let received_ping; + client.on("ping", payload => { + received_ping = payload; + }); + const result = await promise; + expect(typeof result.duration).toBe("number"); + expect(result.payload).toBeInstanceOf(Buffer); + expect(result.payload.byteLength).toBe(8); + expect(received_ping).toBeInstanceOf(Buffer); + expect(received_ping.byteLength).toBe(8); + expect(received_ping).toEqual(result.payload); + }); + it("ping with wrong payload length events should error", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + client.on("connect", () => { + client.ping(Buffer.from("oops"), (err, duration, payload) => { + if (err) { + resolve(err); + } else { + reject("unreachable"); + } + client.close(); + }); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_PING_LENGTH"); + }); + it("ping with wrong payload type events should throw", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + client.on("connect", () => { + try { + client.ping("oops", (err, duration, payload) => { + reject("unreachable"); + client.close(); + }); + } catch (err) { + resolve(err); + client.close(); + } + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_INVALID_ARG_TYPE"); + }); + it("stream event should work", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + client.on("stream", stream => { + resolve(stream); + client.close(); + }); + client.request({ ":path": "/" }).end(); + const stream = await promise; + expect(stream).toBeDefined(); + expect(stream.id).toBe(1); + }); - it("should receive goaway", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const server = await nodeDynamicServer( - "http2.away.1.js", - ` + it("wantTrailers should work", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS); + client.on("error", reject); + const headers = { ":path": "/", ":method": "POST", "x-wait-trailer": "true" }; + const req = client.request(headers, { + waitForTrailers: true, + }); + req.setEncoding("utf8"); + let response_headers; + req.on("response", headers => { + response_headers = headers; + }); + let trailers = { "x-trailer": "hello" }; + req.on("wantTrailers", () => { + req.sendTrailers(trailers); + }); + let data = ""; + req.on("data", chunk => { + data += chunk; + client.close(); + }); + req.on("error", reject); + req.on("end", () => { + resolve({ data, headers: response_headers }); + client.close(); + }); + req.end("hello"); + const response = await promise; + let parsed; + expect(() => (parsed = JSON.parse(response.data))).not.toThrow(); + expect(parsed.headers[":method"]).toEqual(headers[":method"]); + expect(parsed.headers[":path"]).toEqual(headers[":path"]); + expect(parsed.headers["x-wait-trailer"]).toEqual(headers["x-wait-trailer"]); + expect(parsed.trailers).toEqual(trailers); + expect(response.headers[":status"]).toBe(200); + expect(response.headers["set-cookie"]).toEqual([ + "a=b", + "c=d; Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly", + "e=f", + ]); + }); + + it.skipIf(!isCI)( + "should not leak memory", + () => { + const { stdout, exitCode } = Bun.spawnSync({ + cmd: [bunExe(), "--smol", "run", path.join(import.meta.dir, "node-http2-memory-leak.js")], + env: { + ...bunEnv, + BUN_JSC_forceRAMSize: (1024 * 1024 * 64).toString("10"), + HTTP2_SERVER_INFO: JSON.stringify(nodeEchoServer_), + HTTP2_SERVER_TLS: JSON.stringify(TLS_OPTIONS), + }, + stderr: "inherit", + stdin: "inherit", + stdout: "inherit", + }); + expect(exitCode || 0).toBe(0); + }, + 100000, + ); + + it("should receive goaway", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const server = await nodeDynamicServer( + "http2.away.1.js", + ` server.on("stream", (stream, headers, flags) => { stream.session.goaway(http2.constants.NGHTTP2_CONNECT_ERROR, 0, Buffer.from("123456")); }); `, - ); - try { - const client = http2.connect(server.url); - client.on("goaway", (...params) => resolve(params)); - client.on("error", reject); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.on("error", err => { - if (err.errno !== http2.constants.NGHTTP2_CONNECT_ERROR) { - reject(err); - } + ); + try { + const client = http2.connect(server.url); + client.on("goaway", (...params) => resolve(params)); + client.on("error", reject); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.on("error", err => { + if (err.errno !== http2.constants.NGHTTP2_CONNECT_ERROR) { + reject(err); + } + }); + req.end(); }); - req.end(); - }); - const result = await promise; - expect(result).toBeDefined(); - const [code, lastStreamID, opaqueData] = result; - expect(code).toBe(http2.constants.NGHTTP2_CONNECT_ERROR); - expect(lastStreamID).toBe(1); - expect(opaqueData.toString()).toBe("123456"); - } finally { - server.subprocess.kill(); - } - }); - it("should receive goaway without debug data", async () => { - const { promise, resolve, reject } = Promise.withResolvers(); - const server = await nodeDynamicServer( - "http2.away.2.js", - ` + const result = await promise; + expect(result).toBeDefined(); + const [code, lastStreamID, opaqueData] = result; + expect(code).toBe(http2.constants.NGHTTP2_CONNECT_ERROR); + expect(lastStreamID).toBe(1); + expect(opaqueData.toString()).toBe("123456"); + } finally { + server.subprocess.kill(); + } + }); + it("should receive goaway without debug data", async () => { + const { promise, resolve, reject } = Promise.withResolvers(); + const server = await nodeDynamicServer( + "http2.away.2.js", + ` server.on("stream", (stream, headers, flags) => { stream.session.goaway(http2.constants.NGHTTP2_CONNECT_ERROR, 0); }); `, - ); - try { - const client = http2.connect(server.url); - client.on("goaway", (...params) => resolve(params)); - client.on("error", reject); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.on("error", err => { - if (err.errno !== http2.constants.NGHTTP2_CONNECT_ERROR) { - reject(err); - } - }); - req.end(); - }); - const result = await promise; - expect(result).toBeDefined(); - const [code, lastStreamID, opaqueData] = result; - expect(code).toBe(http2.constants.NGHTTP2_CONNECT_ERROR); - expect(lastStreamID).toBe(1); - expect(opaqueData.toString()).toBe(""); - } finally { - server.subprocess.kill(); - } - }); - it("should not be able to write on socket", done => { - const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS, (session, socket) => { + ); try { - client.socket.write("hello"); - client.socket.end(); - expect().fail("unreachable"); - } catch (err) { + const client = http2.connect(server.url); + client.on("goaway", (...params) => resolve(params)); + client.on("error", reject); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.on("error", err => { + if (err.errno !== http2.constants.NGHTTP2_CONNECT_ERROR) { + reject(err); + } + }); + req.end(); + }); + const result = await promise; + expect(result).toBeDefined(); + const [code, lastStreamID, opaqueData] = result; + expect(code).toBe(http2.constants.NGHTTP2_CONNECT_ERROR); + expect(lastStreamID).toBe(1); + expect(opaqueData.toString()).toBe(""); + } finally { + server.subprocess.kill(); + } + }); + it("should not be able to write on socket", done => { + const client = http2.connect(HTTPS_SERVER, TLS_OPTIONS, (session, socket) => { try { - expect(err.code).toBe("ERR_HTTP2_NO_SOCKET_MANIPULATION"); + client.socket.write("hello"); + client.socket.end(); + expect().fail("unreachable"); + } catch (err) { + try { + expect(err.code).toBe("ERR_HTTP2_NO_SOCKET_MANIPULATION"); + } catch (err) { + done(err); + } + done(); + } + }); + }); + it("should handle bad GOAWAY server frame size", done => { + const server = net.createServer(socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + const frame = new http2utils.Frame(7, 7, 0, 0).data; + socket.write(Buffer.concat([frame, Buffer.alloc(7)])); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); + done(); } catch (err) { done(err); + } finally { + server.close(); } - done(); - } + }); }); - }); - it("should handle bad GOAWAY server frame size", done => { - const server = net.createServer(socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - const frame = new http2utils.Frame(7, 7, 0, 0).data; - socket.write(Buffer.concat([frame, Buffer.alloc(7)])); + it("should handle bad DATA_FRAME server frame size", done => { + const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); + const server = net.createServer(async socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + await waitToWrite; + const frame = new http2utils.DataFrame(1, Buffer.alloc(16384 * 2), 0, 1).data; + socket.write(frame); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + allowWrite(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); + done(); + } catch (err) { + done(err); + } finally { + server.close(); + } + }); }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } + it("should handle bad RST_FRAME server frame size (no stream)", done => { + const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); + const server = net.createServer(async socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + await waitToWrite; + const frame = new http2utils.Frame(4, 3, 0, 0).data; + socket.write(Buffer.concat([frame, Buffer.alloc(4)])); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + allowWrite(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_PROTOCOL_ERROR"); + done(); + } catch (err) { + done(err); + } finally { + server.close(); + } + }); }); - }); - it("should handle bad DATA_FRAME server frame size", done => { - const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); - const server = net.createServer(async socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - await waitToWrite; - const frame = new http2utils.DataFrame(1, Buffer.alloc(16384 * 2), 0, 1).data; - socket.write(frame); + it("should handle bad RST_FRAME server frame size (less than allowed)", done => { + const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); + const server = net.createServer(async socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + await waitToWrite; + const frame = new http2utils.Frame(3, 3, 0, 1).data; + socket.write(Buffer.concat([frame, Buffer.alloc(3)])); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + allowWrite(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); + done(); + } catch (err) { + done(err); + } finally { + server.close(); + } + }); }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - allowWrite(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } + it("should handle bad RST_FRAME server frame size (more than allowed)", done => { + const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); + const server = net.createServer(async socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + await waitToWrite; + const buffer = Buffer.alloc(16384 * 2); + const frame = new http2utils.Frame(buffer.byteLength, 3, 0, 1).data; + socket.write(Buffer.concat([frame, buffer])); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + allowWrite(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); + done(); + } catch (err) { + done(err); + } finally { + server.close(); + } + }); }); - }); - it("should handle bad RST_FRAME server frame size (no stream)", done => { - const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); - const server = net.createServer(async socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - await waitToWrite; - const frame = new http2utils.Frame(4, 3, 0, 0).data; - socket.write(Buffer.concat([frame, Buffer.alloc(4)])); - }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - allowWrite(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_PROTOCOL_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } - }); - }); - it("should handle bad RST_FRAME server frame size (less than allowed)", done => { - const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); - const server = net.createServer(async socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - await waitToWrite; - const frame = new http2utils.Frame(3, 3, 0, 1).data; - socket.write(Buffer.concat([frame, Buffer.alloc(3)])); - }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - allowWrite(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } - }); - }); - it("should handle bad RST_FRAME server frame size (more than allowed)", done => { - const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); - const server = net.createServer(async socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - await waitToWrite; - const buffer = Buffer.alloc(16384 * 2); - const frame = new http2utils.Frame(buffer.byteLength, 3, 0, 1).data; - socket.write(Buffer.concat([frame, buffer])); - }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - allowWrite(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } - }); - }); - it("should handle bad CONTINUATION_FRAME server frame size", done => { - const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); - const server = net.createServer(async socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - await waitToWrite; + it("should handle bad CONTINUATION_FRAME server frame size", done => { + const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); + const server = net.createServer(async socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + await waitToWrite; - const frame = new http2utils.HeadersFrame(1, http2utils.kFakeResponseHeaders, 0, true, false); - socket.write(frame.data); - const continuationFrame = new http2utils.ContinuationFrame( - 1, - http2utils.kFakeResponseHeaders, - 0, - true, - false, - ); - socket.write(continuationFrame.data); + const frame = new http2utils.HeadersFrame(1, http2utils.kFakeResponseHeaders, 0, true, false); + socket.write(frame.data); + const continuationFrame = new http2utils.ContinuationFrame( + 1, + http2utils.kFakeResponseHeaders, + 0, + true, + false, + ); + socket.write(continuationFrame.data); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + allowWrite(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_PROTOCOL_ERROR"); + done(); + } catch (err) { + done(err); + } finally { + server.close(); + } + }); }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - allowWrite(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_PROTOCOL_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } - }); - }); - it("should handle bad PRIOTITY_FRAME server frame size", done => { - const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); - const server = net.createServer(async socket => { - const settings = new http2utils.SettingsFrame(true); - socket.write(settings.data); - await waitToWrite; + it("should handle bad PRIOTITY_FRAME server frame size", done => { + const { promise: waitToWrite, resolve: allowWrite } = Promise.withResolvers(); + const server = net.createServer(async socket => { + const settings = new http2utils.SettingsFrame(true); + socket.write(settings.data); + await waitToWrite; - const frame = new http2utils.Frame(4, 2, 0, 1).data; - socket.write(Buffer.concat([frame, Buffer.alloc(4)])); - }); - server.listen(0, "127.0.0.1", async () => { - const url = `http://127.0.0.1:${server.address().port}`; - try { - const { promise, resolve } = Promise.withResolvers(); - const client = http2.connect(url); - client.on("error", resolve); - client.on("connect", () => { - const req = client.request({ ":path": "/" }); - req.end(); - allowWrite(); - }); - const result = await promise; - expect(result).toBeDefined(); - expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); - expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); - done(); - } catch (err) { - done(err); - } finally { - server.close(); - } + const frame = new http2utils.Frame(4, 2, 0, 1).data; + socket.write(Buffer.concat([frame, Buffer.alloc(4)])); + }); + server.listen(0, "127.0.0.1", async () => { + const url = `http://127.0.0.1:${server.address().port}`; + try { + const { promise, resolve } = Promise.withResolvers(); + const client = http2.connect(url); + client.on("error", resolve); + client.on("connect", () => { + const req = client.request({ ":path": "/" }); + req.end(); + allowWrite(); + }); + const result = await promise; + expect(result).toBeDefined(); + expect(result.code).toBe("ERR_HTTP2_SESSION_ERROR"); + expect(result.message).toBe("Session closed with error code NGHTTP2_FRAME_SIZE_ERROR"); + done(); + } catch (err) { + done(err); + } finally { + server.close(); + } + }); }); }); }); - }); + } } it("sensitive headers should work", async () => { diff --git a/test/js/node/process/process-stdin.test.ts b/test/js/node/process/process-stdin.test.ts index 1dddd12b87..51a5aebacb 100644 --- a/test/js/node/process/process-stdin.test.ts +++ b/test/js/node/process/process-stdin.test.ts @@ -21,10 +21,135 @@ test("file does the right thing", async () => { cmd: [bunExe(), "-e", "console.log(typeof process.stdin.ref)"], stdin: Bun.file(import.meta.path), stdout: "pipe", - stderr: "inherit", + stderr: "pipe", env: bunEnv, }); - expect((await new Response(result.stdout).text()).trim()).toBe("undefined"); + expect(await result.stdout.text()).toMatchInlineSnapshot(` + "undefined + " + `); + expect(await result.stderr.text()).toMatchInlineSnapshot(`""`); expect(await result.exited).toBe(0); }); + +test("stdin with 'readable' event handler should receive data when paused", async () => { + const proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + const handleReadable = () => { + let chunk; + while ((chunk = process.stdin.read())) { + console.log("got chunk", JSON.stringify(chunk)); + } + }; + + process.stdin.on("readable", handleReadable); + process.stdin.pause(); + + setTimeout(() => { + process.exit(1); + }, 1000); + `, + ], + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + env: bunEnv, + }); + + proc.stdin.write("abc\n"); + proc.stdin.write("def\n"); + proc.stdin.end(); + + await proc.exited; + + expect(await proc.stdout.text()).toMatchInlineSnapshot(` + "got chunk {"type":"Buffer","data":[97,98,99,10,100,101,102,10]} + " + `); + expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`); + expect(proc.exitCode).toBe(1); +}); + +test("stdin with 'data' event handler should NOT receive data when paused", async () => { + const proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + const handleData = chunk => { + console.log("got chunk"); + }; + + process.stdin.on("data", handleData); + process.stdin.pause(); + + setTimeout(() => { + process.exit(1); + }, 1000); + `, + ], + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + env: bunEnv, + }); + + proc.stdin.write("abc\n"); + proc.stdin.write("def\n"); + proc.stdin.end(); + + const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]); + + expect(await proc.stdout.text()).toMatchInlineSnapshot(`""`); + expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`); + expect(proc.exitCode).toBe(1); +}); + +test("stdin should allow process to exit when paused", async () => { + const proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + process.stdin.on("data", () => {}); + process.stdin.pause(); + `, + ], + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + env: bunEnv, + }); + + await proc.exited; + expect(await proc.stdout.text()).toMatchInlineSnapshot(`""`); + expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`); + expect(proc.exitCode).toBe(0); +}); + +test("stdin should not allow process to exit when not paused", async () => { + const proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + process.stdin.on("data", () => {}); + `, + ], + stdin: "pipe", + stdout: "pipe", + stderr: "pipe", + env: bunEnv, + }); + + await Bun.sleep(1000); + expect(proc.exitCode).toBe(null); + proc.kill(); + await proc.exited; + expect(await proc.stdout.text()).toMatchInlineSnapshot(`""`); + expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`); +}); diff --git a/test/js/node/process/stdin/data.fixture.js b/test/js/node/process/stdin/data.fixture.js new file mode 100644 index 0000000000..7aa5335576 --- /dev/null +++ b/test/js/node/process/stdin/data.fixture.js @@ -0,0 +1,8 @@ +console.log("%READY%"); + +const d = data => { + console.log("got data", JSON.stringify(data.toString())); + console.log("%READY%"); +}; + +process.stdin.on("data", d); diff --git a/test/js/node/process/stdin/pause.fixture.js b/test/js/node/process/stdin/pause.fixture.js new file mode 100644 index 0000000000..958d1cfed3 --- /dev/null +++ b/test/js/node/process/stdin/pause.fixture.js @@ -0,0 +1,35 @@ +console.log("%READY%"); + +const r = () => { + let chunk; + if (ceaseReading) return; + while ((chunk = process.stdin.read()) !== null) { + console.log("got readable", JSON.stringify(chunk.toString())); + } +}; + +let ceaseReading = false; +process.stdin.on("data", data => { + const dataString = data.toString().trim(); + console.log("got stdin", JSON.stringify(dataString)); + if (dataString === "pause") { + process.stdin.pause(); + } else if (dataString === "attachReadable") { + process.stdin.on("readable", r); + } else if (dataString === "detachReadable") { + process.stdin.off("readable", r); + return; + } else if (dataString === "ceaseReading") { + ceaseReading = true; + } else if (dataString === "exit") { + process.exit(123); + } + console.log("%READY%"); +}); + +process.on("beforeExit", code => { + console.log("beforeExit with code " + code); +}); +process.on("exit", code => { + console.log("exit with code " + code); +}); diff --git a/test/js/node/process/stdin/readable.fixture.js b/test/js/node/process/stdin/readable.fixture.js new file mode 100644 index 0000000000..708db5dd74 --- /dev/null +++ b/test/js/node/process/stdin/readable.fixture.js @@ -0,0 +1,11 @@ +console.log("%READY%"); + +const r = () => { + let chunk; + while ((chunk = process.stdin.read()) !== null) { + console.log("got readable", JSON.stringify(chunk.toString())); + console.log("%READY%"); + } +}; + +process.stdin.on("readable", r); diff --git a/test/js/node/process/stdin/stdin-fixtures.test.ts b/test/js/node/process/stdin/stdin-fixtures.test.ts new file mode 100644 index 0000000000..fc1db59833 --- /dev/null +++ b/test/js/node/process/stdin/stdin-fixtures.test.ts @@ -0,0 +1,213 @@ +import { spawn } from "child_process"; +import path from "path"; +import { bunExe } from "harness"; + +type Test = { + file: string; + stdin: string[]; + end: boolean; +}; + +type RunResult = { + exitCode: number | null; + stdout: string; + stderr: string; + autoKilled: boolean; +}; + +async function run(cmd: string, test: Test): Promise { + return new Promise((resolve, reject) => { + const scriptPath = path.join(import.meta.dir, test.file); + + const child = spawn(cmd, [scriptPath], { + stdio: "pipe", + }); + + let autoKilled = false; + setTimeout(() => { + autoKilled = true; + child.kill("SIGTERM"); + }, 1000); + + child.on("error", err => { + reject(err); + }); + + let stdout = ""; + let stderr = ""; + const remainingToSend = [...test.stdin]; + let processedReadyCount = 0; + + child.stdout.setEncoding("utf8"); + child.stderr.setEncoding("utf8"); + + child.stdout.on("data", chunk => { + chunk = chunk.replaceAll("\r", ""); + stdout += chunk; + // Count occurrences of "%READY%" to know when to send stdin + const currentReadyCount = (stdout.match(/%READY%/g) || []).length; + + if (currentReadyCount > processedReadyCount) { + const numNewReady = currentReadyCount - processedReadyCount; + processedReadyCount = currentReadyCount; + + for (let i = 0; i < numNewReady; i++) { + const toSend = remainingToSend.shift(); + if (toSend !== undefined) { + child.stdin.write(toSend); + } else { + if (test.end) { + // If we've run out of input and the test expects stdin to be closed. + if (child.stdin.writable && !child.stdin.writableEnded) { + child.stdin.end(); + } + } else { + // Script is asking for more input, but we have none. This is an error. + child.kill(); // Ensure the process is terminated + reject(new Error(`[${cmd}] No more stdin to send, but script requested more.`)); + return; // Prevent further processing + } + } + } + } + }); + + child.stderr.on("data", chunk => { + chunk = chunk.replaceAll("\r", ""); + stderr += chunk; + }); + + let exitCode: number | null = null; + child.on("exit", code => { + exitCode = code; + }); + + // The 'close' event fires after the process exits and all stdio streams are closed. + // This is the safest point to resolve the promise with the final results. + child.on("close", () => { + // Check if we failed to send all required input. + if (remainingToSend.length > 0) { + reject(new Error(`[${cmd}] Not all stdin was sent. Unsent: ${JSON.stringify(remainingToSend)}`)); + return; + } + + resolve({ + exitCode, + stdout, + stderr, + autoKilled, + }); + }); + }); +} + +async function runBoth(test: Test): Promise { + const nodeResult = await run("node", test); + // console.log("Node.js Result:", nodeResult); + + const bunResult = await run(bunExe(), test); + // console.log("Bun Result:", bunResult); + + expect(bunResult).toEqual(nodeResult); + return bunResult; +} + +describe("stdin", () => { + it("pause allows process to exit", async () => { + // in node, raw stdin behaves differently than pty. run this test in bun only for now. + expect(await run(bunExe(), { file: "pause.fixture.js", stdin: ["abc\n", "pause\n", "def\n"], end: false })) + .toMatchInlineSnapshot(` + { + "autoKilled": false, + "exitCode": 0, + "stderr": "", + "stdout": + "%READY% + got stdin "abc" + %READY% + got stdin "pause" + %READY% + beforeExit with code 0 + exit with code 0 + " + , + } + `); + }); + it("pause with readable listener does not allow process to exit", async () => { + expect( + await runBoth({ + file: "pause.fixture.js", + stdin: ["attachReadable\n", "abc\n", "pause\n", "def\n", "exit\n"], + end: false, + }), + ).toMatchInlineSnapshot(` + { + "autoKilled": false, + "exitCode": 123, + "stderr": "", + "stdout": + "%READY% + got stdin "attachReadable" + %READY% + got stdin "abc" + %READY% + got readable "abc\\n" + got stdin "pause" + %READY% + got readable "pause\\n" + got stdin "def" + %READY% + got readable "def\\n" + got stdin "exit" + exit with code 123 + " + , + } + `); + }); + it("unref-should-exit", async () => { + expect(await runBoth({ file: "unref-should-exit.fixture.js", stdin: [], end: false })).toMatchInlineSnapshot(` + { + "autoKilled": false, + "exitCode": 0, + "stderr": "", + "stdout": "", + } + `); + }); + it("works with data listener", async () => { + expect(await runBoth({ file: "data.fixture.js", stdin: ["abc\n", "def\n"], end: true })).toMatchInlineSnapshot(` + { + "autoKilled": false, + "exitCode": 0, + "stderr": "", + "stdout": + "%READY% + got data "abc\\n" + %READY% + got data "def\\n" + %READY% + " + , + } + `); + }); + it("works with readable listener", async () => { + expect(await runBoth({ file: "readable.fixture.js", stdin: ["abc\n", "def\n"], end: true })).toMatchInlineSnapshot(` + { + "autoKilled": false, + "exitCode": 0, + "stderr": "", + "stdout": + "%READY% + got readable "abc\\n" + %READY% + got readable "def\\n" + %READY% + " + , + } + `); + }); +}); diff --git a/test/js/node/process/stdin/unref-should-exit.fixture.js b/test/js/node/process/stdin/unref-should-exit.fixture.js new file mode 100644 index 0000000000..ad8d502542 --- /dev/null +++ b/test/js/node/process/stdin/unref-should-exit.fixture.js @@ -0,0 +1,9 @@ +let count = 0; +process.stdin.on("data", data => { + count += 1; + console.log("got " + count, JSON.stringify(data.toString("utf-8"))); + if (count >= 2) { + timeout.unref(); + } +}); +process.stdin.unref(); // prevent stdin from keeping the process alive, but still allow reading from stdin diff --git a/test/js/node/test/parallel/test-http2-client-proxy-over-http2.js b/test/js/node/test/parallel/test-http2-client-proxy-over-http2.js new file mode 100644 index 0000000000..71efee1e07 --- /dev/null +++ b/test/js/node/test/parallel/test-http2-client-proxy-over-http2.js @@ -0,0 +1,50 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const h2 = require('http2'); + +const server = h2.createServer(); + +server.listen(0, common.mustCall(function() { + const proxyClient = h2.connect(`http://127.0.0.1:${server.address().port}`); + + const request = proxyClient.request({ + ':method': 'CONNECT', + ':authority': 'example.com:80' + }); + + request.on('response', common.mustCall((connectResponse) => { + assert.strictEqual(connectResponse[':status'], 200); + + const proxiedClient = h2.connect('http://example.com', { + createConnection: () => request // Tunnel via first request stream + }); + + const proxiedRequest = proxiedClient.request(); + proxiedRequest.on('response', common.mustCall((proxiedResponse) => { + assert.strictEqual(proxiedResponse[':status'], 204); + + proxiedClient.close(); + proxyClient.close(); + server.close(); + })); + })); +})); + +server.once('connect', common.mustCall((req, res) => { + assert.strictEqual(req.headers[':method'], 'CONNECT'); + res.writeHead(200); // Accept the CONNECT tunnel + + // Handle this stream as a new 'proxied' connection (pretend to forward + // but actually just unwrap the tunnel ourselves): + server.emit('connection', res.stream); +})); + +// Handle the 'proxied' request itself: +server.once('request', common.mustCall((req, res) => { + res.writeHead(204); + res.end(); +})); diff --git a/test/js/node/test/parallel/test-http2-generic-streams-sendfile.js b/test/js/node/test/parallel/test-http2-generic-streams-sendfile.js new file mode 100644 index 0000000000..36288aef5b --- /dev/null +++ b/test/js/node/test/parallel/test-http2-generic-streams-sendfile.js @@ -0,0 +1,38 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const http2 = require('http2'); +const fs = require('fs'); +const { duplexPair } = require('stream'); + +{ + const server = http2.createServer(); + server.on('stream', common.mustCall((stream, headers) => { + stream.respondWithFile(__filename); + })); + + const [ clientSide, serverSide ] = duplexPair(); + server.emit('connection', serverSide); + + const client = http2.connect('http://127.0.0.1:80', { + createConnection: common.mustCall(() => clientSide) + }); + + const req = client.request(); + + req.on('response', common.mustCall((headers) => { + assert.strictEqual(headers[':status'], 200); + })); + + req.setEncoding('utf8'); + let data = ''; + req.on('data', (chunk) => data += chunk); + req.on('end', common.mustCall(() => { + assert.strictEqual(data, fs.readFileSync(__filename, 'utf8')); + clientSide.destroy(); + clientSide.end(); + })); + req.end(); +} diff --git a/test/js/node/test/parallel/test-http2-padding-aligned.js b/test/js/node/test/parallel/test-http2-padding-aligned.js new file mode 100644 index 0000000000..55629246ee --- /dev/null +++ b/test/js/node/test/parallel/test-http2-padding-aligned.js @@ -0,0 +1,72 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const http2 = require('http2'); +const { PADDING_STRATEGY_ALIGNED, PADDING_STRATEGY_CALLBACK } = http2.constants; +const { duplexPair } = require('stream'); + +{ + const testData = '

Hello World.

'; // 21 should generate 24 bytes data + const server = http2.createServer({ + paddingStrategy: PADDING_STRATEGY_ALIGNED + }); + server.on('stream', common.mustCall((stream, headers) => { + stream.respond({ + 'content-type': 'text/html', + ':status': 200 + }); + stream.end(testData); + })); + + const [ clientSide, serverSide ] = duplexPair(); + +// The lengths of the expected writes... note that this is highly +// sensitive to how the internals are implemented and may differ from node.js due to corking and settings. + +// 45 is the settings frame (9 + 36) +// 9 + 9 + 40 are settings ACK window update and byte frames +// 24 is the data (divisible by 8 because of padding) +// 9 is the end of the stream +const clientLengths = [45, 9, 9, 40, 9, 24, 9]; + + +// 45 for settings (9 + 36) +// 15 for headers and frame bytes +// 24 for data (divisible by 8 because of padding) +// 9 for ending the stream because we did in 2 steps (request + end) +const serverLengths = [93, 9]; + + server.emit('connection', serverSide); + + const client = http2.connect('http://127.0.0.1:80', { + paddingStrategy: PADDING_STRATEGY_ALIGNED, + createConnection: common.mustCall(() => clientSide) + }); + + serverSide.on('data', common.mustCall((chunk) => { + assert.strictEqual(chunk.length, serverLengths.shift()); + }, serverLengths.length)); + clientSide.on('data', common.mustCall((chunk) => { + assert.strictEqual(chunk.length, clientLengths.shift()); + }, clientLengths.length)); + + const req = client.request({ ':path': '/a' }); + + req.on('response', common.mustCall()); + + req.setEncoding('utf8'); + req.on('data', common.mustCall((data) => { + assert.strictEqual(data, testData); + })); + req.on('close', common.mustCall(() => { + clientSide.destroy(); + clientSide.end(); + })); + req.end(); +} + +// PADDING_STRATEGY_CALLBACK has been aliased to mean aligned padding. +assert.strictEqual(PADDING_STRATEGY_ALIGNED, PADDING_STRATEGY_CALLBACK); diff --git a/test/js/node/test/parallel/test-http2-write-finishes-after-stream-destroy.js b/test/js/node/test/parallel/test-http2-write-finishes-after-stream-destroy.js new file mode 100644 index 0000000000..e47c6d7100 --- /dev/null +++ b/test/js/node/test/parallel/test-http2-write-finishes-after-stream-destroy.js @@ -0,0 +1,62 @@ +// Flags: --expose-gc +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const http2 = require('http2'); +const { duplexPair } = require('stream'); + +// Make sure the Http2Stream destructor works, since we don't clean the +// stream up like we would otherwise do. +process.on('exit', globalThis.gc); + +{ + const [ clientSide, serverSide ] = duplexPair(); + + let serverSideHttp2Stream; + let serverSideHttp2StreamDestroyed = false; + const server = http2.createServer(); + server.on('stream', common.mustCall((stream, headers) => { + serverSideHttp2Stream = stream; + stream.respond({ + 'content-type': 'text/html', + ':status': 200 + }); + + const originalWrite = serverSide._write; + serverSide._write = (buf, enc, cb) => { + if (serverSideHttp2StreamDestroyed) { + serverSide.destroy(); + serverSide.write = () => {}; + } else { + setImmediate(() => { + originalWrite.call(serverSide, buf, enc, () => setImmediate(cb)); + }); + } + }; + + // Enough data to fit into a single *session* window, + // not enough data to fit into a single *stream* window. + stream.write(Buffer.alloc(40000)); + })); + + server.emit('connection', serverSide); + + const client = http2.connect('http://127.0.0.1:80', { + createConnection: common.mustCall(() => clientSide) + }); + + const req = client.request({ ':path': '/' }); + + req.on('response', common.mustCall((headers) => { + assert.strictEqual(headers[':status'], 200); + })); + + req.on('data', common.mustCallAtLeast(() => { + if (!serverSideHttp2StreamDestroyed) { + serverSideHttp2Stream.destroy(); + serverSideHttp2StreamDestroyed = true; + } + })); +} diff --git a/test/js/node/tls/node-tls-cert.test.ts b/test/js/node/tls/node-tls-cert.test.ts index dcd457b604..13f1899a16 100644 --- a/test/js/node/tls/node-tls-cert.test.ts +++ b/test/js/node/tls/node-tls-cert.test.ts @@ -1,11 +1,11 @@ -import { expect, it } from "bun:test"; +import { describe, expect, it } from "bun:test"; +import { once } from "events"; import { readFileSync } from "fs"; import { bunEnv, bunExe, invalidTls, tmpdirSync } from "harness"; import type { AddressInfo } from "node:net"; import type { Server, TLSSocket } from "node:tls"; import { join } from "path"; import tls from "tls"; - const clientTls = { key: readFileSync(join(import.meta.dir, "fixtures", "ec10-key.pem"), "utf8"), cert: readFileSync(join(import.meta.dir, "fixtures", "ec10-cert.pem"), "utf8"), @@ -568,3 +568,43 @@ it("tls.connect should ignore NODE_EXTRA_CA_CERTS if it contains invalid cert", expect(stderr).toContain("ignoring extra certs"); } }); +describe("tls ciphers should work", () => { + [ + "", // when using BoringSSL we cannot set the cipher suites directly in this case, but we can set empty ciphers + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES128-SHA256", + ].forEach(cipher_name => { + it(`tls.connect should use ${cipher_name || "empty"}`, async () => { + const server = tls.createServer({ + key: serverTls.key, + cert: serverTls.cert, + passphrase: "123123123", + ciphers: cipher_name, + }); + let socket: TLSSocket | null = null; + try { + await once(server.listen(0, "127.0.0.1"), "listening"); + + socket = tls.connect({ + port: (server.address() as AddressInfo).port, + host: "127.0.0.1", + ca: serverTls.ca, + ciphers: cipher_name, + }); + await once(socket, "secureConnect"); + } finally { + socket?.end(); + server.close(); + } + }); + }); + + it("default ciphers should match expected", () => { + expect(tls.DEFAULT_CIPHERS).toBe( + "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA", + ); + }); +}); diff --git a/test/js/sql/issue-21351.fixture.sql b/test/js/sql/issue-21351.fixture.sql new file mode 100644 index 0000000000..bd0cf171c4 --- /dev/null +++ b/test/js/sql/issue-21351.fixture.sql @@ -0,0 +1,155 @@ +-- Insert 50 Users +INSERT INTO users (id, name, email, identifier, role, phone, bio, skills, privacy, linkedin_url, github_url, facebook_url, twitter_url, picture) VALUES +('alice01', 'Alice Anderson', 'alice01@example.com', 'alice01', 'CUSTOMER', '+1-555-111-0001', '{"about": "Data Scientist", "location": "Los Angeles"}', '["Figma", "Sketch", "UI/UX"]', 'PRIVATE', NULL, 'https://github.com/alice01', NULL, NULL, '{"url": "https://pics.example.com/alice01.jpg"}'), +('bob02', 'Bob Moore', 'bob02@example.com', 'bob02', 'CUSTOMER', '+1-555-111-0002', '{"about": "Cloud Engineer", "location": "Seattle"}', '["Figma", "Sketch", "UI/UX"]', 'PRIVATE', 'https://linkedin.com/in/bob02', 'https://github.com/bob02', NULL, 'https://twitter.com/bob02', '{"url": "https://pics.example.com/bob02.jpg"}'), +('charlie03', 'Charlie Adams', 'charlie03@example.com', 'charlie03', 'CUSTOMER', '+1-555-111-0003', '{"about": "Digital Marketer", "location": "Boston"}', '["Java", "Spring Boot", "Microservices"]', 'PUBLIC', NULL, 'https://github.com/charlie03', NULL, 'https://twitter.com/charlie03', '{"url": "https://pics.example.com/charlie03.jpg"}'), +('diana04', 'Diana Johnson', 'diana04@example.com', 'diana04', 'CUSTOMER', '+1-555-111-0004', '{"about": "Digital Marketer", "location": "New York"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', NULL, 'https://github.com/diana04', NULL, 'https://twitter.com/diana04', '{"url": "https://pics.example.com/diana04.jpg"}'), +('ethan05', 'Ethan Brown', 'ethan05@example.com', 'ethan05', 'CUSTOMER', '+1-555-111-0005', '{"about": "Digital Marketer", "location": "Seattle"}', '["Flutter", "Dart", "Firebase"]', 'PRIVATE', 'https://linkedin.com/in/ethan05', 'https://github.com/ethan05', NULL, 'https://twitter.com/ethan05', '{"url": "https://pics.example.com/ethan05.jpg"}'), +('fiona06', 'Fiona Adams', 'fiona06@example.com', 'fiona06', 'CUSTOMER', '+1-555-111-0006', '{"about": "Digital Marketer", "location": "Los Angeles"}', '["Kubernetes", "Docker", "CI/CD"]', 'PUBLIC', 'https://linkedin.com/in/fiona06', 'https://github.com/fiona06', NULL, 'https://twitter.com/fiona06', '{"url": "https://pics.example.com/fiona06.jpg"}'), +('george07', 'George Wilson', 'george07@example.com', 'george07', 'CUSTOMER', '+1-555-111-0007', '{"about": "Data Scientist", "location": "Los Angeles"}', '["Python", "Pandas", "Machine Learning"]', 'PRIVATE', 'https://linkedin.com/in/george07', NULL, NULL, 'https://twitter.com/george07', '{"url": "https://pics.example.com/george07.jpg"}'), +('hannah08', 'Hannah Moore', 'hannah08@example.com', 'hannah08', 'CUSTOMER', '+1-555-111-0008', '{"about": "UX Designer", "location": "Chicago"}', '["Deep Learning", "NLP", "PyTorch"]', 'PUBLIC', 'https://linkedin.com/in/hannah08', 'https://github.com/hannah08', NULL, NULL, '{"url": "https://pics.example.com/hannah08.jpg"}'), +('ian09', 'Ian Adams', 'ian09@example.com', 'ian09', 'CUSTOMER', '+1-555-111-0009', '{"about": "Cloud Engineer", "location": "Boston"}', '["Deep Learning", "NLP", "PyTorch"]', 'PRIVATE', 'https://linkedin.com/in/ian09', 'https://github.com/ian09', NULL, 'https://twitter.com/ian09', '{"url": "https://pics.example.com/ian09.jpg"}'), +('julia10', 'Julia Thomas', 'julia10@example.com', 'julia10', 'CUSTOMER', '+1-555-111-0010', '{"about": "Cloud Engineer", "location": "New York"}', '["Python", "Pandas", "Machine Learning"]', 'PUBLIC', 'https://linkedin.com/in/julia10', NULL, NULL, 'https://twitter.com/julia10', '{"url": "https://pics.example.com/julia10.jpg"}'), +('kevin11', 'Kevin Wilson', 'kevin11@example.com', 'kevin11', 'CUSTOMER', '+1-555-111-0011', '{"about": "Full stack developer", "location": "New York"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', NULL, NULL, NULL, 'https://twitter.com/kevin11', '{"url": "https://pics.example.com/kevin11.jpg"}'), +('laura12', 'Laura Lee', 'laura12@example.com', 'laura12', 'CUSTOMER', '+1-555-111-0012', '{"about": "Full stack developer", "location": "Chicago"}', '["Kubernetes", "Docker", "CI/CD"]', 'PUBLIC', 'https://linkedin.com/in/laura12', NULL, NULL, NULL, '{"url": "https://pics.example.com/laura12.jpg"}'), +('mike13', 'Mike Wilson', 'mike13@example.com', 'mike13', 'CUSTOMER', '+1-555-111-0013', '{"about": "Full stack developer", "location": "San Francisco"}', '["Deep Learning", "NLP", "PyTorch"]', 'PUBLIC', 'https://linkedin.com/in/mike13', 'https://github.com/mike13', NULL, NULL, '{"url": "https://pics.example.com/mike13.jpg"}'), +('nina14', 'Nina Wilson', 'nina14@example.com', 'nina14', 'CUSTOMER', '+1-555-111-0014', '{"about": "UX Designer", "location": "Seattle"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', 'https://linkedin.com/in/nina14', 'https://github.com/nina14', NULL, NULL, '{"url": "https://pics.example.com/nina14.jpg"}'), +('oscar15', 'Oscar Johnson', 'oscar15@example.com', 'oscar15', 'CUSTOMER', '+1-555-111-0015', '{"about": "Cloud Engineer", "location": "Boston"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', NULL, 'https://github.com/oscar15', NULL, NULL, '{"url": "https://pics.example.com/oscar15.jpg"}'), +('paula16', 'Paula Taylor', 'paula16@example.com', 'paula16', 'CUSTOMER', '+1-555-111-0016', '{"about": "Cloud Engineer", "location": "New York"}', '["Deep Learning", "NLP", "PyTorch"]', 'PRIVATE', 'https://linkedin.com/in/paula16', NULL, NULL, 'https://twitter.com/paula16', '{"url": "https://pics.example.com/paula16.jpg"}'), +('quinn17', 'Quinn Thomas', 'quinn17@example.com', 'quinn17', 'CUSTOMER', '+1-555-111-0017', '{"about": "Full stack developer", "location": "New York"}', '["Python", "Pandas", "Machine Learning"]', 'PUBLIC', 'https://linkedin.com/in/quinn17', NULL, NULL, NULL, '{"url": "https://pics.example.com/quinn17.jpg"}'), +('ryan18', 'Ryan Wilson', 'ryan18@example.com', 'ryan18', 'CUSTOMER', '+1-555-111-0018', '{"about": "UX Designer", "location": "Los Angeles"}', '["Deep Learning", "NLP", "PyTorch"]', 'PUBLIC', 'https://linkedin.com/in/ryan18', 'https://github.com/ryan18', NULL, NULL, '{"url": "https://pics.example.com/ryan18.jpg"}'), +('sophia19', 'Sophia Lee', 'sophia19@example.com', 'sophia19', 'CUSTOMER', '+1-555-111-0019', '{"about": "Mobile App Developer", "location": "San Francisco"}', '["Flutter", "Dart", "Firebase"]', 'PUBLIC', 'https://linkedin.com/in/sophia19', 'https://github.com/sophia19', NULL, NULL, '{"url": "https://pics.example.com/sophia19.jpg"}'), +('tom20', 'Tom Thomas', 'tom20@example.com', 'tom20', 'CUSTOMER', '+1-555-111-0020', '{"about": "Digital Marketer", "location": "Chicago"}', '["AWS", "Terraform", "DevOps"]', 'PRIVATE', 'https://linkedin.com/in/tom20', 'https://github.com/tom20', NULL, 'https://twitter.com/tom20', '{"url": "https://pics.example.com/tom20.jpg"}'), +('uma21', 'Uma Johnson', 'uma21@example.com', 'uma21', 'CUSTOMER', '+1-555-111-0021', '{"about": "Data Scientist", "location": "Los Angeles"}', '["Java", "Spring Boot", "Microservices"]', 'PRIVATE', 'https://linkedin.com/in/uma21', NULL, NULL, NULL, '{"url": "https://pics.example.com/uma21.jpg"}'), +('victor22', 'Victor Brown', 'victor22@example.com', 'victor22', 'CUSTOMER', '+1-555-111-0022', '{"about": "Cloud Engineer", "location": "New York"}', '["Deep Learning", "NLP", "PyTorch"]', 'PUBLIC', 'https://linkedin.com/in/victor22', 'https://github.com/victor22', NULL, 'https://twitter.com/victor22', '{"url": "https://pics.example.com/victor22.jpg"}'), +('wendy23', 'Wendy Anderson', 'wendy23@example.com', 'wendy23', 'CUSTOMER', '+1-555-111-0023', '{"about": "Mobile App Developer", "location": "Chicago"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', 'https://linkedin.com/in/wendy23', 'https://github.com/wendy23', NULL, 'https://twitter.com/wendy23', '{"url": "https://pics.example.com/wendy23.jpg"}'), +('xavier24', 'Xavier Taylor', 'xavier24@example.com', 'xavier24', 'CUSTOMER', '+1-555-111-0024', '{"about": "Digital Marketer", "location": "Boston"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', 'https://linkedin.com/in/xavier24', 'https://github.com/xavier24', NULL, 'https://twitter.com/xavier24', '{"url": "https://pics.example.com/xavier24.jpg"}'), +('yara25', 'Yara Brown', 'yara25@example.com', 'yara25', 'CUSTOMER', '+1-555-111-0025', '{"about": "UX Designer", "location": "New York"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', NULL, NULL, NULL, 'https://twitter.com/yara25', '{"url": "https://pics.example.com/yara25.jpg"}'), +('zane26', 'Zane Taylor', 'zane26@example.com', 'zane26', 'CUSTOMER', '+1-555-111-0026', '{"about": "Cloud Engineer", "location": "Seattle"}', '["JavaScript", "React", "Node.js"]', 'PUBLIC', 'https://linkedin.com/in/zane26', 'https://github.com/zane26', NULL, 'https://twitter.com/zane26', '{"url": "https://pics.example.com/zane26.jpg"}'), +('amber27', 'Amber Wilson', 'amber27@example.com', 'amber27', 'CUSTOMER', '+1-555-111-0027', '{"about": "Digital Marketer", "location": "New York"}', '["Kubernetes", "Docker", "CI/CD"]', 'PUBLIC', NULL, 'https://github.com/amber27', NULL, 'https://twitter.com/amber27', '{"url": "https://pics.example.com/amber27.jpg"}'), +('brian28', 'Brian Wilson', 'brian28@example.com', 'brian28', 'CUSTOMER', '+1-555-111-0028', '{"about": "Digital Marketer", "location": "Chicago"}', '["Figma", "Sketch", "UI/UX"]', 'PRIVATE', 'https://linkedin.com/in/brian28', NULL, NULL, 'https://twitter.com/brian28', '{"url": "https://pics.example.com/brian28.jpg"}'), +('carmen29', 'Carmen Moore', 'carmen29@example.com', 'carmen29', 'CUSTOMER', '+1-555-111-0029', '{"about": "Digital Marketer", "location": "Boston"}', '["Kubernetes", "Docker", "CI/CD"]', 'PRIVATE', 'https://linkedin.com/in/carmen29', NULL, NULL, 'https://twitter.com/carmen29', '{"url": "https://pics.example.com/carmen29.jpg"}'), +('daniel30', 'Daniel Smith', 'daniel30@example.com', 'daniel30', 'CUSTOMER', '+1-555-111-0030', '{"about": "Full stack developer", "location": "New York"}', '["AWS", "Terraform", "DevOps"]', 'PUBLIC', 'https://linkedin.com/in/daniel30', 'https://github.com/daniel30', NULL, NULL, '{"url": "https://pics.example.com/daniel30.jpg"}'), +('elena31', 'Elena Lee', 'elena31@example.com', 'elena31', 'CUSTOMER', '+1-555-111-0031', '{"about": "Mobile App Developer", "location": "San Francisco"}', '["SEO", "Content Marketing"]', 'PRIVATE', NULL, 'https://github.com/elena31', NULL, NULL, '{"url": "https://pics.example.com/elena31.jpg"}'), +('frank32', 'Frank Johnson', 'frank32@example.com', 'frank32', 'CUSTOMER', '+1-555-111-0032', '{"about": "Digital Marketer", "location": "San Francisco"}', '["AWS", "Terraform", "DevOps"]', 'PUBLIC', 'https://linkedin.com/in/frank32', 'https://github.com/frank32', NULL, 'https://twitter.com/frank32', '{"url": "https://pics.example.com/frank32.jpg"}'), +('grace33', 'Grace Adams', 'grace33@example.com', 'grace33', 'CUSTOMER', '+1-555-111-0033', '{"about": "Mobile App Developer", "location": "Seattle"}', '["AWS", "Terraform", "DevOps"]', 'PUBLIC', NULL, 'https://github.com/grace33', NULL, 'https://twitter.com/grace33', '{"url": "https://pics.example.com/grace33.jpg"}'), +('henry34', 'Henry Adams', 'henry34@example.com', 'henry34', 'CUSTOMER', '+1-555-111-0034', '{"about": "AI Researcher", "location": "San Francisco"}', '["JavaScript", "React", "Node.js"]', 'PUBLIC', 'https://linkedin.com/in/henry34', 'https://github.com/henry34', NULL, 'https://twitter.com/henry34', '{"url": "https://pics.example.com/henry34.jpg"}'), +('isla35', 'Isla Adams', 'isla35@example.com', 'isla35', 'CUSTOMER', '+1-555-111-0035', '{"about": "Cloud Engineer", "location": "Los Angeles"}', '["Flutter", "Dart", "Firebase"]', 'PRIVATE', NULL, 'https://github.com/isla35', NULL, 'https://twitter.com/isla35', '{"url": "https://pics.example.com/isla35.jpg"}'), +('jack36', 'Jack Johnson', 'jack36@example.com', 'jack36', 'CUSTOMER', '+1-555-111-0036', '{"about": "UX Designer", "location": "Seattle"}', '["Kubernetes", "Docker", "CI/CD"]', 'PRIVATE', 'https://linkedin.com/in/jack36', NULL, NULL, NULL, '{"url": "https://pics.example.com/jack36.jpg"}'), +('kara37', 'Kara Moore', 'kara37@example.com', 'kara37', 'CUSTOMER', '+1-555-111-0037', '{"about": "Data Scientist", "location": "Chicago"}', '["JavaScript", "React", "Node.js"]', 'PRIVATE', 'https://linkedin.com/in/kara37', 'https://github.com/kara37', NULL, 'https://twitter.com/kara37', '{"url": "https://pics.example.com/kara37.jpg"}'), +('liam38', 'Liam Adams', 'liam38@example.com', 'liam38', 'CUSTOMER', '+1-555-111-0038', '{"about": "Cloud Engineer", "location": "Seattle"}', '["Python", "Pandas", "Machine Learning"]', 'PUBLIC', 'https://linkedin.com/in/liam38', 'https://github.com/liam38', NULL, 'https://twitter.com/liam38', '{"url": "https://pics.example.com/liam38.jpg"}'), +('maya39', 'Maya Brown', 'maya39@example.com', 'maya39', 'CUSTOMER', '+1-555-111-0039', '{"about": "UX Designer", "location": "Los Angeles"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', NULL, 'https://github.com/maya39', NULL, 'https://twitter.com/maya39', '{"url": "https://pics.example.com/maya39.jpg"}'), +('noah40', 'Noah Johnson', 'noah40@example.com', 'noah40', 'CUSTOMER', '+1-555-111-0040', '{"about": "Cloud Engineer", "location": "Chicago"}', '["Kubernetes", "Docker", "CI/CD"]', 'PRIVATE', 'https://linkedin.com/in/noah40', 'https://github.com/noah40', NULL, 'https://twitter.com/noah40', '{"url": "https://pics.example.com/noah40.jpg"}'), +('olivia41', 'Olivia Thomas', 'olivia41@example.com', 'olivia41', 'CUSTOMER', '+1-555-111-0041', '{"about": "AI Researcher", "location": "Boston"}', '["Java", "Spring Boot", "Microservices"]', 'PRIVATE', 'https://linkedin.com/in/olivia41', 'https://github.com/olivia41', NULL, 'https://twitter.com/olivia41', '{"url": "https://pics.example.com/olivia41.jpg"}'), +('peter42', 'Peter Adams', 'peter42@example.com', 'peter42', 'CUSTOMER', '+1-555-111-0042', '{"about": "Cloud Engineer", "location": "New York"}', '["JavaScript", "React", "Node.js"]', 'PRIVATE', 'https://linkedin.com/in/peter42', 'https://github.com/peter42', NULL, NULL, '{"url": "https://pics.example.com/peter42.jpg"}'), +('queen43', 'Queen Brown', 'queen43@example.com', 'queen43', 'CUSTOMER', '+1-555-111-0043', '{"about": "UX Designer", "location": "Seattle"}', '["SEO", "Content Marketing"]', 'PRIVATE', NULL, NULL, NULL, 'https://twitter.com/queen43', '{"url": "https://pics.example.com/queen43.jpg"}'), +('rita44', 'Rita Moore', 'rita44@example.com', 'rita44', 'CUSTOMER', '+1-555-111-0044', '{"about": "Mobile App Developer", "location": "Los Angeles"}', '["Deep Learning", "NLP", "PyTorch"]', 'PRIVATE', NULL, 'https://github.com/rita44', NULL, 'https://twitter.com/rita44', '{"url": "https://pics.example.com/rita44.jpg"}'), +('samuel45', 'Samuel Moore', 'samuel45@example.com', 'samuel45', 'CUSTOMER', '+1-555-111-0045', '{"about": "Full stack developer", "location": "Boston"}', '["Go", "gRPC", "PostgreSQL"]', 'PRIVATE', 'https://linkedin.com/in/samuel45', NULL, NULL, 'https://twitter.com/samuel45', '{"url": "https://pics.example.com/samuel45.jpg"}'), +('tina46', 'Tina Wilson', 'tina46@example.com', 'tina46', 'CUSTOMER', '+1-555-111-0046', '{"about": "Mobile App Developer", "location": "Los Angeles"}', '["Python", "Pandas", "Machine Learning"]', 'PUBLIC', 'https://linkedin.com/in/tina46', 'https://github.com/tina46', NULL, 'https://twitter.com/tina46', '{"url": "https://pics.example.com/tina46.jpg"}'), +('ursula47', 'Ursula Wilson', 'ursula47@example.com', 'ursula47', 'CUSTOMER', '+1-555-111-0047', '{"about": "Digital Marketer", "location": "Seattle"}', '["Flutter", "Dart", "Firebase"]', 'PUBLIC', NULL, 'https://github.com/ursula47', NULL, 'https://twitter.com/ursula47', '{"url": "https://pics.example.com/ursula47.jpg"}'), +('vera48', 'Vera Anderson', 'vera48@example.com', 'vera48', 'CUSTOMER', '+1-555-111-0048', '{"about": "Cloud Engineer", "location": "San Francisco"}', '["AWS", "Terraform", "DevOps"]', 'PUBLIC', 'https://linkedin.com/in/vera48', 'https://github.com/vera48', NULL, 'https://twitter.com/vera48', '{"url": "https://pics.example.com/vera48.jpg"}'), +('william49', 'William Lee', 'william49@example.com', 'william49', 'CUSTOMER', '+1-555-111-0049', '{"about": "AI Researcher", "location": "Los Angeles"}', '["Go", "gRPC", "PostgreSQL"]', 'PUBLIC', 'https://linkedin.com/in/william49', 'https://github.com/william49', NULL, NULL, '{"url": "https://pics.example.com/william49.jpg"}'), +('zoe50', 'Zoe Thomas', 'zoe50@example.com', 'zoe50', 'CUSTOMER', '+1-555-111-0050', '{"about": "Digital Marketer", "location": "Los Angeles"}', '["Flutter", "Dart", "Firebase"]', 'PRIVATE', NULL, 'https://github.com/zoe50', NULL, NULL, '{"url": "https://pics.example.com/zoe50.jpg"}'); + +-- Insert 100+ Posts (2 per user) +INSERT INTO posts (user_id, title, content, tags, type, attachments) VALUES +('alice01', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["React", "JavaScript"]', 'draft', '[{"url": "https://files.example.com/intro-to-machine-learning.pdf"}]'), +('alice01', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["DevOps", "Cloud"]', 'published', '[{"url": "https://files.example.com/advanced-node.js-patterns.pdf"}]'), +('bob02', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["NLP", "AI"]', 'published', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('bob02', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["Python", "Pandas"]', 'published', '[{"url": "https://files.example.com/intro-to-machine-learning.pdf"}]'), +('charlie03', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["Python", "Pandas"]', 'published', '[{"url": "https://files.example.com/data-cleaning-with-pandas.pdf"}]'), +('charlie03', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["DevOps", "Cloud"]', 'draft', '[]'), +('diana04', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["DevOps", "Cloud"]', 'draft', '[]'), +('diana04', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["Python", "Pandas"]', 'draft', '[]'), +('ethan05', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["Deep Learning", "Python"]', 'draft', '[]'), +('ethan05', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["Backend", "Node.js"]', 'published', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('fiona06', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["ML", "AI"]', 'draft', '[]'), +('fiona06', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["React", "JavaScript"]', 'draft', '[]'), +('george07', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["ML", "AI"]', 'published', '[]'), +('george07', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["ML", "AI"]', 'published', '[{"url": "https://files.example.com/building-mobile-apps-with-flutter.pdf"}]'), +('hannah08', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["ML", "AI"]', 'published', '[{"url": "https://files.example.com/ui-design-best-practices.pdf"}]'), +('hannah08', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["Kubernetes", "Docker"]', 'published', '[]'), +('ian09', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["UI", "Design"]', 'draft', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('ian09', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["ML", "AI"]', 'published', '[{"url": "https://files.example.com/data-cleaning-with-pandas.pdf"}]'), +('julia10', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["ML", "AI"]', 'draft', '[]'), +('julia10', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["Deep Learning", "Python"]', 'published', '[{"url": "https://files.example.com/understanding-react-hooks.pdf"}]'), +('kevin11', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["NLP", "AI"]', 'published', '[]'), +('kevin11', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["Python", "Pandas"]', 'published', '[]'), +('laura12', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["DevOps", "Cloud"]', 'draft', '[]'), +('laura12', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["NLP", "AI"]', 'draft', '[{"url": "https://files.example.com/intro-to-machine-learning.pdf"}]'), +('mike13', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["ML", "AI"]', 'draft', '[]'), +('mike13', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["Kubernetes", "Docker"]', 'draft', '[]'), +('nina14', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["UI", "Design"]', 'draft', '[]'), +('nina14', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["UI", "Design"]', 'draft', '[{"url": "https://files.example.com/ui-design-best-practices.pdf"}]'), +('oscar15', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["NLP", "AI"]', 'published', '[{"url": "https://files.example.com/understanding-react-hooks.pdf"}]'), +('oscar15', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["NLP", "AI"]', 'published', '[]'), +('paula16', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["Python", "Pandas"]', 'draft', '[]'), +('paula16', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["Kubernetes", "Docker"]', 'draft', '[{"url": "https://files.example.com/kubernetes-basics.pdf"}]'), +('quinn17', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["ML", "AI"]', 'published', '[]'), +('quinn17', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["Deep Learning", "Python"]', 'published', '[{"url": "https://files.example.com/getting-started-with-nlp.pdf"}]'), +('ryan18', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["React", "JavaScript"]', 'published', '[]'), +('ryan18', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Python", "Pandas"]', 'draft', '[]'), +('sophia19', 'Deep Learning for Beginners', '{"text": "This is a detailed guide about Deep Learning for Beginners."}', '["NLP", "AI"]', 'published', '[]'), +('sophia19', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Mobile", "Flutter"]', 'draft', '[]'), +('tom20', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["Python", "Pandas"]', 'draft', '[]'), +('tom20', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["NLP", "AI"]', 'published', '[]'), +('uma21', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["Backend", "Node.js"]', 'draft', '[{"url": "https://files.example.com/kubernetes-basics.pdf"}]'), +('uma21', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["Mobile", "Flutter"]', 'draft', '[]'), +('victor22', 'Deep Learning for Beginners', '{"text": "This is a detailed guide about Deep Learning for Beginners."}', '["Python", "Pandas"]', 'draft', '[]'), +('victor22', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["UI", "Design"]', 'published', '[{"url": "https://files.example.com/building-mobile-apps-with-flutter.pdf"}]'), +('wendy23', 'Deep Learning for Beginners', '{"text": "This is a detailed guide about Deep Learning for Beginners."}', '["NLP", "AI"]', 'draft', '[{"url": "https://files.example.com/deep-learning-for-beginners.pdf"}]'), +('wendy23', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Backend", "Node.js"]', 'draft', '[{"url": "https://files.example.com/advanced-node.js-patterns.pdf"}]'), +('xavier24', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["UI", "Design"]', 'published', '[]'), +('xavier24', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Python", "Pandas"]', 'draft', '[]'), +('yara25', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["Deep Learning", "Python"]', 'published', '[]'), +('yara25', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["NLP", "AI"]', 'published', '[]'), +('zane26', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["React", "JavaScript"]', 'draft', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('zane26', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["NLP", "AI"]', 'draft', '[]'), +('amber27', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["DevOps", "Cloud"]', 'draft', '[{"url": "https://files.example.com/kubernetes-basics.pdf"}]'), +('amber27', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["Mobile", "Flutter"]', 'draft', '[]'), +('brian28', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["Backend", "Node.js"]', 'draft', '[{"url": "https://files.example.com/ui-design-best-practices.pdf"}]'), +('brian28', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["React", "JavaScript"]', 'draft', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('carmen29', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["DevOps", "Cloud"]', 'published', '[{"url": "https://files.example.com/intro-to-machine-learning.pdf"}]'), +('carmen29', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["NLP", "AI"]', 'published', '[]'), +('daniel30', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["ML", "AI"]', 'draft', '[{"url": "https://files.example.com/building-mobile-apps-with-flutter.pdf"}]'), +('daniel30', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["NLP", "AI"]', 'draft', '[]'), +('elena31', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["React", "JavaScript"]', 'draft', '[{"url": "https://files.example.com/getting-started-with-nlp.pdf"}]'), +('elena31', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Python", "Pandas"]', 'draft', '[{"url": "https://files.example.com/advanced-node.js-patterns.pdf"}]'), +('frank32', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["ML", "AI"]', 'draft', '[{"url": "https://files.example.com/kubernetes-basics.pdf"}]'), +('frank32', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["UI", "Design"]', 'draft', '[{"url": "https://files.example.com/building-mobile-apps-with-flutter.pdf"}]'), +('grace33', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["ML", "AI"]', 'draft', '[{"url": "https://files.example.com/getting-started-with-nlp.pdf"}]'), +('grace33', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["Mobile", "Flutter"]', 'draft', '[]'), +('henry34', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["ML", "AI"]', 'published', '[]'), +('henry34', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Mobile", "Flutter"]', 'draft', '[{"url": "https://files.example.com/advanced-node.js-patterns.pdf"}]'), +('isla35', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["Backend", "Node.js"]', 'draft', '[{"url": "https://files.example.com/understanding-react-hooks.pdf"}]'), +('isla35', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["ML", "AI"]', 'published', '[{"url": "https://files.example.com/kubernetes-basics.pdf"}]'), +('jack36', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["UI", "Design"]', 'draft', '[{"url": "https://files.example.com/getting-started-with-nlp.pdf"}]'), +('jack36', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["Deep Learning", "Python"]', 'draft', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('kara37', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["NLP", "AI"]', 'published', '[]'), +('kara37', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["UI", "Design"]', 'published', '[{"url": "https://files.example.com/ui-design-best-practices.pdf"}]'), +('liam38', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["React", "JavaScript"]', 'published', '[]'), +('liam38', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["UI", "Design"]', 'published', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('maya39', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["React", "JavaScript"]', 'draft', '[]'), +('maya39', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["Deep Learning", "Python"]', 'published', '[]'), +('noah40', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["Deep Learning", "Python"]', 'published', '[]'), +('noah40', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["Deep Learning", "Python"]', 'draft', '[]'), +('olivia41', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["Deep Learning", "Python"]', 'published', '[]'), +('olivia41', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["Deep Learning", "Python"]', 'draft', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('peter42', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["NLP", "AI"]', 'draft', '[{"url": "https://files.example.com/getting-started-with-nlp.pdf"}]'), +('peter42', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["Mobile", "Flutter"]', 'published', '[{"url": "https://files.example.com/intro-to-machine-learning.pdf"}]'), +('queen43', 'Docker for Developers', '{"text": "This is a detailed guide about Docker for Developers."}', '["ML", "AI"]', 'published', '[{"url": "https://files.example.com/docker-for-developers.pdf"}]'), +('queen43', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["Python", "Pandas"]', 'draft', '[]'), +('rita44', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["Deep Learning", "Python"]', 'published', '[{"url": "https://files.example.com/ui-design-best-practices.pdf"}]'), +('rita44', 'Kubernetes Basics', '{"text": "This is a detailed guide about Kubernetes Basics."}', '["DevOps", "Cloud"]', 'published', '[{"url": "https://files.example.com/kubernetes-basics.pdf"}]'), +('samuel45', 'Understanding React Hooks', '{"text": "This is a detailed guide about Understanding React Hooks."}', '["React", "JavaScript"]', 'draft', '[{"url": "https://files.example.com/understanding-react-hooks.pdf"}]'), +('samuel45', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["ML", "AI"]', 'published', '[{"url": "https://files.example.com/building-mobile-apps-with-flutter.pdf"}]'), +('tina46', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["Kubernetes", "Docker"]', 'draft', '[]'), +('tina46', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["UI", "Design"]', 'published', '[]'), +('ursula47', 'UI Design Best Practices', '{"text": "This is a detailed guide about UI Design Best Practices."}', '["UI", "Design"]', 'published', '[{"url": "https://files.example.com/ui-design-best-practices.pdf"}]'), +('ursula47', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["Deep Learning", "Python"]', 'published', '[]'), +('vera48', 'Getting Started with NLP', '{"text": "This is a detailed guide about Getting Started with NLP."}', '["ML", "AI"]', 'published', '[]'), +('vera48', 'Advanced Node.js Patterns', '{"text": "This is a detailed guide about Advanced Node.js Patterns."}', '["Python", "Pandas"]', 'published', '[{"url": "https://files.example.com/advanced-node.js-patterns.pdf"}]'), +('william49', 'Data Cleaning with Pandas', '{"text": "This is a detailed guide about Data Cleaning with Pandas."}', '["Kubernetes", "Docker"]', 'published', '[{"url": "https://files.example.com/data-cleaning-with-pandas.pdf"}]'), +('william49', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["DevOps", "Cloud"]', 'published', '[{"url": "https://files.example.com/intro-to-machine-learning.pdf"}]'), +('zoe50', 'Intro to Machine Learning', '{"text": "This is a detailed guide about Intro to Machine Learning."}', '["DevOps", "Cloud"]', 'published', '[]'), +('zoe50', 'Building Mobile Apps with Flutter', '{"text": "This is a detailed guide about Building Mobile Apps with Flutter."}', '["Deep Learning", "Python"]', 'published', '[]'); \ No newline at end of file diff --git a/test/js/sql/local-sql.test.ts b/test/js/sql/local-sql.test.ts index 0cf3df97c8..21d95453ab 100644 --- a/test/js/sql/local-sql.test.ts +++ b/test/js/sql/local-sql.test.ts @@ -1,6 +1,6 @@ import { SQL } from "bun"; import { afterAll, expect, test } from "bun:test"; -import { isLinux } from "harness"; +import { bunEnv, bunExe, isLinux, tempDirWithFiles } from "harness"; import path from "path"; const postgres = (...args) => new SQL(...args); @@ -26,8 +26,9 @@ async function waitForPostgres(port) { for (let i = 0; i < 3; i++) { try { const sql = new SQL(`postgres://bun_sql_test@localhost:${port}/bun_sql_test`, { - idle_timeout: 20, - max_lifetime: 60 * 30, + idleTimeout: 1, + connectionTimeout: 1, + maxLifetime: 1, tls: { ca: Bun.file(path.join(import.meta.dir, "docker-tls", "server.crt")), }, @@ -64,7 +65,6 @@ async function startContainer(): Promise<{ port: number; containerName: string } // Start the container await execAsync(`${dockerCLI} run -d --name ${containerName} -p ${port}:5432 custom-postgres-tls`); - // Wait for PostgreSQL to be ready await waitForPostgres(port); return { @@ -148,4 +148,196 @@ if (isDockerEnabled()) { const result = (await sql`select 1 as x`)[0].x; expect(result).toBe(1); }); + + test("should not segfault under pressure #21351", async () => { + // we need at least the usename and port + await using sql = postgres(connectionString, { + max: 1, + idleTimeout: 1, + connectionTimeout: 1, + tls: { + rejectUnauthorized: false, + }, + }); + await sql`create table users ( + id text not null, + created_at timestamp with time zone not null default now(), + name text null, + email text null, + identifier text not null default '-'::text, + role text null default 'CUSTOMER'::text, + phone text null, + bio jsonb null, + skills jsonb null default '[]'::jsonb, + privacy text null default 'PUBLIC'::text, + linkedin_url text null, + github_url text null, + facebook_url text null, + twitter_url text null, + picture jsonb null, + constraint users_pkey primary key (id), + constraint users_identifier_key unique (identifier) + ) TABLESPACE pg_default; + create table posts ( + id uuid not null default gen_random_uuid (), + created_at timestamp with time zone not null default now(), + user_id text null, + title text null, + content jsonb null, + tags jsonb null, + type text null default 'draft'::text, + attachments jsonb null default '[]'::jsonb, + updated_at timestamp with time zone null, + constraint posts_pkey primary key (id), + constraint posts_user_id_fkey foreign KEY (user_id) references users (id) on update CASCADE on delete CASCADE + ) TABLESPACE pg_default;`.simple(); + await sql.file(path.join(import.meta.dirname, "issue-21351.fixture.sql")); + + const dir = tempDirWithFiles("import-meta-no-inline", { + "index.ts": ` + import { SQL } from "bun"; + + const db = new SQL({ + url: process.env.DATABASE_URL, + max: 1, + idleTimeout: 60 * 5, + maxLifetime: 60 * 15, + tls: { + ca: Bun.file(process.env.DATABASE_CA as string), + }, + }); + await db.connect(); + const server = Bun.serve({ + port: 0, + fetch: async (req) => { + try{ + await Bun.sleep(100); + let fragment = db\`\`; + + const searchs = await db\` + WITH cte AS ( + SELECT + post.id, + post."content", + post.created_at AS "createdAt", + users."name" AS "userName", + users.id AS "userId", + users.identifier AS "userIdentifier", + users.picture AS "userPicture", + '{}'::json AS "group" + FROM posts post + INNER JOIN users + ON users.id = post.user_id + \${fragment} + ORDER BY post.created_at DESC + ) + SELECT + * + FROM cte + -- LIMIT 5 + \`; + return Response.json(searchs); + } catch { + return new Response(null, { status: 500 }); + } + }, + }); + + console.log(server.url.href); + `, + }); + sql.end({ timeout: 0 }); + async function bombardier(url, batchSize = 100, abortSignal) { + let batch = []; + for (let i = 0; i < 100_000 && !abortSignal.aborted; i++) { + //@ts-ignore + batch.push(fetch(url, { signal: abortSignal }).catch(() => {})); + if (batch.length > batchSize) { + await Promise.all(batch); + batch = []; + } + } + await Promise.all(batch); + } + let failed = false; + function spawnServer(controller) { + return new Promise(async (resolve, reject) => { + const server = Bun.spawn([bunExe(), "index.ts"], { + stdin: "ignore", + stdout: "pipe", + stderr: "pipe", + cwd: dir, + env: { + ...bunEnv, + BUN_DEBUG_QUIET_LOGS: "1", + DATABASE_URL: connectionString, + DATABASE_CA: path.join(import.meta.dir, "docker-tls", "server.crt"), + }, + onExit(proc, exitCode, signalCode, error) { + // exit handler + if (exitCode !== 0) { + failed = true; + controller.abort(); + } + }, + }); + + const reader = server.stdout.getReader(); + const errorReader = server.stderr.getReader(); + + const decoder = new TextDecoder(); + async function outputData(reader, type = "log") { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + if (value) { + if (type === "error") { + console.error(decoder.decode(value)); + } else { + console.log(decoder.decode(value)); + } + } + } + } + + const url = decoder.decode((await reader.read()).value); + resolve({ url, kill: () => server.kill() }); + outputData(reader); + errorReader.read().then(({ value }) => { + if (value) { + console.error(decoder.decode(value)); + failed = true; + } + outputData(errorReader, "error"); + }); + }); + } + async function spawnRestarts(controller) { + for (let i = 0; i < 20 && !controller.signal.aborted; i++) { + await Bun.$`${dockerCLI} restart ${container.containerName}`.nothrow().quiet(); + await Bun.sleep(500); + } + + try { + controller.abort(); + } catch {} + } + + const controller = new AbortController(); + + const { promise, resolve, reject } = Promise.withResolvers(); + const server = (await spawnServer(controller)) as { url: string; kill: () => void }; + + controller.signal.addEventListener("abort", () => { + if (!failed) resolve(); + else reject(new Error("Server crashed")); + server.kill(); + }); + + bombardier(server.url, 100, controller.signal); + + await Bun.sleep(1000); + spawnRestarts(controller); + await promise; + }, 30_000); } diff --git a/test/js/sql/socket.fail.fixture.ts b/test/js/sql/socket.fail.fixture.ts new file mode 100644 index 0000000000..401e949fc6 --- /dev/null +++ b/test/js/sql/socket.fail.fixture.ts @@ -0,0 +1,19 @@ +setTimeout(() => { + // no need to wait we know at this point that the test passed + process.exit(0); +}, 100); +for (let i = 0; i < 3; i++) { + try { + const sql = new Bun.SQL({ + url: "postgres://-invalid-:1234/postgres", + max: 1, + idleTimeout: 1, + connectionTimeout: 1, + maxLifetime: 1, + }); + await sql.connect(); + } catch { + } finally { + Bun.gc(true); + } +} diff --git a/test/js/sql/sql-fixture-ref.ts b/test/js/sql/sql-fixture-ref.ts index af8f52dafc..c62080a59a 100644 --- a/test/js/sql/sql-fixture-ref.ts +++ b/test/js/sql/sql-fixture-ref.ts @@ -2,20 +2,44 @@ // 1 // 2 // and exiting with code 0. +// +// Due to pipelining and the way the network stuff works, sometimes the second +// function can finish before the first function. The main purpose of this test +// is that both first() and yo(): +// 1. Keep the event loop alive +// 2. Don't get GC'd too early. +// +// Therefore, we must not keep any references to the promises returned by +// first() or yo(). We must not top-level await the results. import { sql } from "bun"; process.exitCode = 1; +let values = []; + async function first() { const result = await sql`select 1 as x`; - console.log(result[0].x); + values.push(result[0].x); + maybeDone(); } async function yo() { const result2 = await sql`select 2 as x`; - console.log(result2[0].x); - process.exitCode = 0; + values.push(result2[0].x); + maybeDone(); } + first(); Bun.gc(true); yo(); Bun.gc(true); + +function maybeDone() { + if (values.length === 2) { + // Determinism. + values.sort(); + + console.log(values[0]); + console.log(values[1]); + process.exitCode = 0; + } +} diff --git a/test/js/sql/sql.test.ts b/test/js/sql/sql.test.ts index d8475b0164..5ff1791a0a 100644 --- a/test/js/sql/sql.test.ts +++ b/test/js/sql/sql.test.ts @@ -1,6 +1,6 @@ import { $, randomUUIDv7, sql, SQL } from "bun"; import { afterAll, describe, expect, mock, test } from "bun:test"; -import { bunExe, isCI, isLinux, tempDirWithFiles } from "harness"; +import { bunEnv, bunExe, isCI, isLinux, tempDirWithFiles } from "harness"; import path from "path"; const postgres = (...args) => new sql(...args); @@ -11096,3 +11096,16 @@ CREATE TABLE ${table_name} ( }); }); } + +describe("should proper handle connection errors", () => { + test("should not crash if connection fails", async () => { + const result = Bun.spawnSync([bunExe(), path.join(import.meta.dirname, "socket.fail.fixture.ts")], { + cwd: import.meta.dir, + env: bunEnv, + stdin: "ignore", + stdout: "inherit", + stderr: "pipe", + }); + expect(result.stderr?.toString()).toBeFalsy(); + }); +}); diff --git a/test/js/valkey/test-utils.ts b/test/js/valkey/test-utils.ts index 7d9fd69c66..0e364c6343 100644 --- a/test/js/valkey/test-utils.ts +++ b/test/js/valkey/test-utils.ts @@ -13,7 +13,10 @@ export const isEnabled = stdout: "pipe", stderr: "inherit", env: bunEnv, + timeout: 5_000, }); + if (info.exitCode !== 0) return false; + if (info.signalCode) return false; return info.stdout.toString().indexOf("Server Version:") !== -1; } catch (error) { return false; diff --git a/test/js/web/atomics.test.ts b/test/js/web/atomics.test.ts new file mode 100644 index 0000000000..a36b5cf80c --- /dev/null +++ b/test/js/web/atomics.test.ts @@ -0,0 +1,309 @@ +import { describe, expect, test } from "bun:test"; + +describe("Atomics", () => { + describe("basic operations", () => { + test("store and load", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + expect(Atomics.store(view, 0, 42)).toBe(42); + expect(Atomics.load(view, 0)).toBe(42); + + expect(Atomics.store(view, 1, -123)).toBe(-123); + expect(Atomics.load(view, 1)).toBe(-123); + }); + + test("add", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 10); + expect(Atomics.add(view, 0, 5)).toBe(10); // returns old value + expect(Atomics.load(view, 0)).toBe(15); // new value + + expect(Atomics.add(view, 0, -3)).toBe(15); + expect(Atomics.load(view, 0)).toBe(12); + }); + + test("sub", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 20); + expect(Atomics.sub(view, 0, 5)).toBe(20); // returns old value + expect(Atomics.load(view, 0)).toBe(15); // new value + + expect(Atomics.sub(view, 0, -3)).toBe(15); + expect(Atomics.load(view, 0)).toBe(18); + }); + + test("exchange", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 100); + expect(Atomics.exchange(view, 0, 200)).toBe(100); + expect(Atomics.load(view, 0)).toBe(200); + }); + + test("compareExchange", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 100); + + // Successful exchange + expect(Atomics.compareExchange(view, 0, 100, 200)).toBe(100); + expect(Atomics.load(view, 0)).toBe(200); + + // Failed exchange (expected value doesn't match) + expect(Atomics.compareExchange(view, 0, 100, 300)).toBe(200); + expect(Atomics.load(view, 0)).toBe(200); // unchanged + }); + }); + + describe("bitwise operations", () => { + test("and", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 0b1111); + expect(Atomics.and(view, 0, 0b1010)).toBe(0b1111); // returns old value + expect(Atomics.load(view, 0)).toBe(0b1010); // new value + }); + + test("or", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 0b1010); + expect(Atomics.or(view, 0, 0b0101)).toBe(0b1010); // returns old value + expect(Atomics.load(view, 0)).toBe(0b1111); // new value + }); + + test("xor", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 0b1010); + expect(Atomics.xor(view, 0, 0b1100)).toBe(0b1010); // returns old value + expect(Atomics.load(view, 0)).toBe(0b0110); // new value (1010 ^ 1100 = 0110) + }); + }); + + describe("utility functions", () => { + test("isLockFree", () => { + expect(typeof Atomics.isLockFree(1)).toBe("boolean"); + expect(typeof Atomics.isLockFree(2)).toBe("boolean"); + expect(typeof Atomics.isLockFree(4)).toBe("boolean"); + expect(typeof Atomics.isLockFree(8)).toBe("boolean"); + + // Most platforms support 4-byte atomic operations + expect(Atomics.isLockFree(4)).toBe(true); + }); + + test("pause", () => { + // pause() should not throw + expect(() => Atomics.pause()).not.toThrow(); + }); + }); + + describe("synchronization", () => { + test("wait with timeout", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 0); + + // Should timeout since no one will notify + const result = Atomics.wait(view, 0, 0, 10); // 10ms timeout + expect(result).toBe("timed-out"); + }); + + test("wait with non-matching value", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 42); + + // Should return immediately since value doesn't match + const result = Atomics.wait(view, 0, 0, 1000); + expect(result).toBe("not-equal"); + }); + + test("notify", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 0); + + // notify returns number of agents that were woken up + // Since no one is waiting, should return 0 + const notified = Atomics.notify(view, 0, 1); + expect(notified).toBe(0); + }); + + test("waitAsync with timeout", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + Atomics.store(view, 0, 0); + + const result = Atomics.waitAsync(view, 0, 0, 10); + expect(typeof result).toBe("object"); + expect(typeof result.async).toBe("boolean"); + + if (result.async) { + expect(result.value).toBeInstanceOf(Promise); + } else { + expect(typeof result.value).toBe("string"); + } + }); + }); + + describe("different TypedArray types", () => { + test("Int8Array", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int8Array(buffer); + + expect(Atomics.store(view, 0, 42)).toBe(42); + expect(Atomics.load(view, 0)).toBe(42); + expect(Atomics.add(view, 0, 8)).toBe(42); + expect(Atomics.load(view, 0)).toBe(50); + }); + + test("Int16Array", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int16Array(buffer); + + expect(Atomics.store(view, 0, 1000)).toBe(1000); + expect(Atomics.load(view, 0)).toBe(1000); + expect(Atomics.sub(view, 0, 200)).toBe(1000); + expect(Atomics.load(view, 0)).toBe(800); + }); + + test("Int32Array", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + expect(Atomics.store(view, 0, 100000)).toBe(100000); + expect(Atomics.load(view, 0)).toBe(100000); + expect(Atomics.exchange(view, 0, 200000)).toBe(100000); + expect(Atomics.load(view, 0)).toBe(200000); + }); + + test("Uint8Array", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Uint8Array(buffer); + + expect(Atomics.store(view, 0, 255)).toBe(255); + expect(Atomics.load(view, 0)).toBe(255); + expect(Atomics.and(view, 0, 0x0f)).toBe(255); + expect(Atomics.load(view, 0)).toBe(0x0f); + }); + + test("Uint16Array", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Uint16Array(buffer); + + expect(Atomics.store(view, 0, 65535)).toBe(65535); + expect(Atomics.load(view, 0)).toBe(65535); + expect(Atomics.or(view, 0, 0xff00)).toBe(65535); + expect(Atomics.load(view, 0)).toBe(65535); + }); + + test("Uint32Array", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Uint32Array(buffer); + + expect(Atomics.store(view, 0, 0xffffffff)).toBe(0xffffffff); + expect(Atomics.load(view, 0)).toBe(0xffffffff); + expect(Atomics.xor(view, 0, 0x12345678)).toBe(0xffffffff); + // Use >>> 0 to convert to unsigned 32-bit for comparison + expect(Atomics.load(view, 0)).toBe((0xffffffff ^ 0x12345678) >>> 0); + }); + + test("BigInt64Array", () => { + const buffer = new SharedArrayBuffer(32); + const view = new BigInt64Array(buffer); + + expect(Atomics.store(view, 0, 42n)).toBe(42n); + expect(Atomics.load(view, 0)).toBe(42n); + expect(Atomics.add(view, 0, 8n)).toBe(42n); + expect(Atomics.load(view, 0)).toBe(50n); + }); + + test("BigUint64Array", () => { + const buffer = new SharedArrayBuffer(32); + const view = new BigUint64Array(buffer); + + expect(Atomics.store(view, 0, 123n)).toBe(123n); + expect(Atomics.load(view, 0)).toBe(123n); + expect(Atomics.compareExchange(view, 0, 123n, 456n)).toBe(123n); + expect(Atomics.load(view, 0)).toBe(456n); + }); + }); + + describe("error cases", () => { + test("works on regular ArrayBuffer in Bun", () => { + // Note: Bun allows Atomics on regular ArrayBuffer, unlike some other engines + const buffer = new ArrayBuffer(16); + const view = new Int32Array(buffer); + + expect(() => Atomics.store(view, 0, 42)).not.toThrow(); + expect(() => Atomics.load(view, 0)).not.toThrow(); + expect(Atomics.load(view, 0)).toBe(42); + }); + + test("throws on non-integer TypedArray", () => { + const buffer = new SharedArrayBuffer(16); + const floatView = new Float32Array(buffer); + + expect(() => Atomics.store(floatView, 0, 1.5)).toThrow(); + expect(() => Atomics.load(floatView, 0)).toThrow(); + }); + + test("throws on out of bounds access", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); // 4 elements (16 bytes / 4 bytes each) + + expect(() => Atomics.store(view, 10, 42)).toThrow(); + expect(() => Atomics.load(view, -1)).toThrow(); + }); + }); + + describe("edge cases", () => { + test("operations at array boundaries", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); // indices 0, 1, 2, 3 + + // Test first element + expect(Atomics.store(view, 0, 100)).toBe(100); + expect(Atomics.load(view, 0)).toBe(100); + + // Test last element + expect(Atomics.store(view, 3, 200)).toBe(200); + expect(Atomics.load(view, 3)).toBe(200); + }); + + test("zero values", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + expect(Atomics.store(view, 0, 0)).toBe(0); + expect(Atomics.load(view, 0)).toBe(0); + expect(Atomics.add(view, 0, 0)).toBe(0); + expect(Atomics.load(view, 0)).toBe(0); + }); + + test("negative values", () => { + const buffer = new SharedArrayBuffer(16); + const view = new Int32Array(buffer); + + expect(Atomics.store(view, 0, -42)).toBe(-42); + expect(Atomics.load(view, 0)).toBe(-42); + expect(Atomics.add(view, 0, -8)).toBe(-42); + expect(Atomics.load(view, 0)).toBe(-50); + }); + }); +}); diff --git a/test/js/web/fetch/blob-write.test.ts b/test/js/web/fetch/blob-write.test.ts new file mode 100644 index 0000000000..89c6ff2243 --- /dev/null +++ b/test/js/web/fetch/blob-write.test.ts @@ -0,0 +1,75 @@ +import { expect, test } from "bun:test"; +import { tempDirWithFiles } from "harness"; +import path from "path"; + +test("blob.write() throws for data-backed blob", () => { + const blob = new Blob(["Hello, world!"]); + expect(() => blob.write("test.txt")).toThrowErrorMatchingInlineSnapshot( + `"Cannot write to a Blob backed by bytes, which are always read-only"`, + ); +}); + +test("Bun.file(path).write() does not throw", async () => { + const file = Bun.file(path.join(tempDirWithFiles("bun-write", { a: "Hello, world!" }), "a")); + expect(() => file.write(new Blob(["Hello, world!!"]))).not.toThrow(); + expect(await file.text()).toBe("Hello, world!!"); +}); + +test("blob.unlink() throws for data-backed blob", () => { + const blob = new Blob(["Hello, world!"]); + expect(() => blob.unlink()).toThrowErrorMatchingInlineSnapshot( + `"Cannot write to a Blob backed by bytes, which are always read-only"`, + ); +}); + +test("blob.delete() throws for data-backed blob", () => { + const blob = new Blob(["Hello, world!"]); + expect(() => blob.delete()).toThrowErrorMatchingInlineSnapshot( + `"Cannot write to a Blob backed by bytes, which are always read-only"`, + ); +}); + +test("Bun.file(path).unlink() does not throw", async () => { + const dir = tempDirWithFiles("bun-unlink", { a: "Hello, world!" }); + const file = Bun.file(path.join(dir, "a")); + expect(file.unlink()).resolves.toBeUndefined(); + expect(await Bun.file(path.join(dir, "a")).exists()).toBe(false); +}); + +test("Bun.file(path).delete() does not throw", async () => { + const dir = tempDirWithFiles("bun-unlink", { a: "Hello, world!" }); + const file = Bun.file(path.join(dir, "a")); + expect(file.delete()).resolves.toBeUndefined(); + expect(await Bun.file(path.join(dir, "a")).exists()).toBe(false); +}); + +test("blob.writer() throws for data-backed blob", () => { + const blob = new Blob(["Hello, world!"]); + expect(() => blob.writer()).toThrowErrorMatchingInlineSnapshot( + `"Cannot write to a Blob backed by bytes, which are always read-only"`, + ); +}); + +test("Bun.file(path).writer() does not throw", async () => { + const dir = tempDirWithFiles("bun-writer", {}); + const file = Bun.file(path.join(dir, "test.txt")); + const writer = file.writer(); + expect(writer).toBeDefined(); + writer.write("New content"); + await writer.end(); + expect(await file.text()).toBe("New content"); +}); + +test("blob.stat() returns undefined for data-backed blob", async () => { + const blob = new Blob(["Hello, world!"]); + const stat = await blob.stat(); + expect(stat).toBeUndefined(); +}); + +test("Bun.file(path).stat() returns stats", async () => { + const dir = tempDirWithFiles("bun-stat", { a: "Hello, world!" }); + const file = Bun.file(path.join(dir, "a")); + const stat = await file.stat(); + expect(stat).toBeDefined(); + expect(stat.size).toBe(13); // "Hello, world!" is 13 bytes +}); diff --git a/test/js/web/fetch/fetch.test.ts b/test/js/web/fetch/fetch.test.ts index a690649ee6..25ec372fdd 100644 --- a/test/js/web/fetch/fetch.test.ts +++ b/test/js/web/fetch/fetch.test.ts @@ -1132,11 +1132,11 @@ describe("Response", () => { "x-hello": "world", Location: "https://wrong.com", }, - status: 408, + status: 307, }); expect(response.headers.get("x-hello")).toBe("world"); expect(response.headers.get("Location")).toBe("https://example.com"); - expect(response.status).toBe(302); + expect(response.status).toBe(307); expect(response.type).toBe("default"); expect(response.ok).toBe(false); }); diff --git a/test/js/web/fetch/response.test.ts b/test/js/web/fetch/response.test.ts index c02d148dd3..c5a249f6d1 100644 --- a/test/js/web/fetch/response.test.ts +++ b/test/js/web/fetch/response.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { sep } from "node:path"; +import { normalizeBunSnapshot } from "harness"; test("zero args returns an otherwise empty 200 response", () => { const response = new Response(); @@ -47,8 +47,9 @@ describe("2-arg form", () => { }); test("print size", () => { - expect(Bun.inspect(new Response(Bun.file(import.meta.filename)))).toMatchInlineSnapshot(` - "Response (1.81 KB) { + expect(normalizeBunSnapshot(Bun.inspect(new Response(Bun.file(import.meta.filename)))), import.meta.dir) + .toMatchInlineSnapshot(` + "Response (3.82 KB) { ok: true, url: "", status: 200, @@ -58,9 +59,53 @@ test("print size", () => { }, redirected: false, bodyUsed: false, - FileRef ("${import.meta.dir}${sep}response.test.ts") { + FileRef ("/test/js/web/fetch/response.test.ts") { type: "text/javascript;charset=utf-8" } }" `); }); + +test("Response.redirect with invalid arguments should not crash", () => { + // This should not crash - issue #18414 + // Passing a number as URL and string as init should handle gracefully + expect(() => Response.redirect(400, "a")).not.toThrow(); + + // Test various invalid argument combinations - should not crash + expect(() => Response.redirect(42, "test")).not.toThrow(); + expect(() => Response.redirect(true, "string")).not.toThrow(); + expect(() => Response.redirect(null, "init")).not.toThrow(); + expect(() => Response.redirect(undefined, "value")).not.toThrow(); +}); + +test("Response.redirect status code validation", () => { + // Valid redirect status codes should work + expect(() => Response.redirect("url", 301)).not.toThrow(); + expect(() => Response.redirect("url", 302)).not.toThrow(); + expect(() => Response.redirect("url", 303)).not.toThrow(); + expect(() => Response.redirect("url", 307)).not.toThrow(); + expect(() => Response.redirect("url", 308)).not.toThrow(); + + // Invalid status codes should throw RangeError + expect(() => Response.redirect("url", 200)).toThrow(RangeError); + expect(() => Response.redirect("url", 400)).toThrow(RangeError); + expect(() => Response.redirect("url", 500)).toThrow(RangeError); + + // Status in object should also be validated + expect(() => Response.redirect("url", { status: 307 })).not.toThrow(); + expect(() => Response.redirect("url", { status: 400 })).toThrow(RangeError); + + // Check that the correct status is set + expect(Response.redirect("url", 301).status).toBe(301); + expect(Response.redirect("url", { status: 308 }).status).toBe(308); +}); + +test("new Response(123, { statusText: 123 }) does not throw", () => { + // @ts-expect-error + expect(new Response("123", { statusText: 123 }).statusText).toBe("123"); +}); + +test("new Response(123, { method: 456 }) does not throw", () => { + // @ts-expect-error + expect(() => new Response("123", { method: 456 })).not.toThrow(); +}); diff --git a/test/js/web/websocket/websocket-blob.test.ts b/test/js/web/websocket/websocket-blob.test.ts new file mode 100644 index 0000000000..c229c5d4b5 --- /dev/null +++ b/test/js/web/websocket/websocket-blob.test.ts @@ -0,0 +1,212 @@ +import { expect, test } from "bun:test"; + +test("WebSocket should send Blob data", async () => { + await using server = Bun.serve({ + port: 0, + websocket: { + open(ws) { + console.log("Server: WebSocket opened"); + }, + message(ws, message) { + console.log("Server received:", message); + // Echo back text messages + ws.send(message); + }, + close(ws) { + console.log("Server: WebSocket closed"); + }, + }, + fetch(req, server) { + if (server.upgrade(req)) { + return undefined; + } + return new Response("Upgrade failed", { status: 500 }); + }, + }); + + const url = `ws://localhost:${server.port}`; + + const { promise, resolve, reject } = Promise.withResolvers(); + const ws = new WebSocket(url); + ws.binaryType = "blob"; + let messageReceived = false; + + ws.onopen = () => { + console.log("Client: WebSocket opened"); + + // Create a blob with test data + const testData = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" in bytes + const blob = new Blob([testData], { type: "application/octet-stream" }); + + console.log("Sending blob with length:", blob.size); + ws.send(blob); + }; + + ws.onmessage = async event => { + console.log("Client received message:", event.data); + messageReceived = true; + + if (event.data instanceof Blob) { + const received = new Uint8Array(await event.data.arrayBuffer()); + console.log("Received bytes:", Array.from(received)); + + // Verify we received the correct data + expect(received).toEqual(new Uint8Array([72, 101, 108, 108, 111])); + ws.close(); + resolve(); + } else { + ws.close(); + reject(new Error("Expected blob data, got: " + typeof event.data)); + } + }; + + ws.onerror = error => { + console.error("WebSocket error:", error); + ws.close(); + reject(error); + }; + + ws.onclose = event => { + console.log("Client: WebSocket closed", event.code, event.reason); + if (!messageReceived) { + reject(new Error("Connection closed without receiving message")); + } + }; + + await promise; +}); + +test("WebSocket should send empty Blob", async () => { + await using server = Bun.serve({ + port: 0, + websocket: { + message(ws, message) { + // Echo back the message + ws.send(message); + }, + }, + fetch(req, server) { + if (server.upgrade(req)) { + return undefined; + } + return new Response("Upgrade failed", { status: 500 }); + }, + }); + + const url = `ws://localhost:${server.port}`; + + const { promise, resolve, reject } = Promise.withResolvers(); + const ws = new WebSocket(url); + ws.binaryType = "blob"; + let messageReceived = false; + + ws.onopen = () => { + // Create an empty blob + const blob = new Blob([], { type: "application/octet-stream" }); + + console.log("Sending empty blob with length:", blob.size); + ws.send(blob); + }; + + ws.onmessage = async event => { + console.log("Client received message:", event.data); + messageReceived = true; + + if (event.data instanceof Blob) { + const received = new Uint8Array(await event.data.arrayBuffer()); + console.log("Received bytes length:", received.length); + + // Verify we received empty data + expect(received.length).toBe(0); + ws.close(); + resolve(); + } else { + ws.close(); + reject(new Error("Expected blob data, got: " + typeof event.data)); + } + }; + + ws.onerror = error => { + console.error("WebSocket error:", error); + ws.close(); + reject(error); + }; + + ws.onclose = event => { + console.log("Client: WebSocket closed", event.code, event.reason); + if (!messageReceived) { + reject(new Error("Connection closed without receiving message")); + } + }; + + await promise; +}); + +test("WebSocket should ping with Blob", async () => { + await using server = Bun.serve({ + port: 0, + websocket: { + ping(ws, data) { + console.log("Server received ping with data:", data); + // Respond with pong containing the same data + ws.pong(data); + }, + }, + fetch(req, server) { + if (server.upgrade(req)) { + return undefined; + } + return new Response("Upgrade failed", { status: 500 }); + }, + }); + + const url = `ws://localhost:${server.port}`; + + const { promise, resolve, reject } = Promise.withResolvers(); + const ws = new WebSocket(url); + ws.binaryType = "blob"; + let pongReceived = false; + + ws.onopen = () => { + console.log("Client: WebSocket opened"); + + // Create a blob with ping data + const pingData = new Uint8Array([80, 73, 78, 71]); // "PING" in bytes + const blob = new Blob([pingData], { type: "application/octet-stream" }); + + console.log("Sending ping with blob"); + ws.ping(blob); + }; + + ws.addEventListener("pong", async (event: any) => { + console.log("Client received pong:", event.data); + pongReceived = true; + + if (event.data instanceof Blob) { + const received = new Uint8Array(await event.data.arrayBuffer()); + + // Verify we received the correct ping data back + expect(new Uint8Array(received)).toEqual(new Uint8Array([80, 73, 78, 71])); + ws.close(); + resolve(); + } else { + ws.close(); + reject(new Error("Expected blob data in pong, got: " + typeof event.data)); + } + }); + + ws.onerror = error => { + console.error("WebSocket error:", error); + ws.close(); + reject(error); + }; + + ws.onclose = event => { + console.log("Client: WebSocket closed", event.code, event.reason); + if (!pongReceived) { + reject(new Error("Connection closed without receiving pong")); + } + }; + + await promise; +}); diff --git a/test/napi/node-napi-tests/harness.ts b/test/napi/node-napi-tests/harness.ts new file mode 100644 index 0000000000..5b511ac346 --- /dev/null +++ b/test/napi/node-napi-tests/harness.ts @@ -0,0 +1,52 @@ +import { spawn, spawnSync } from "bun"; +import { bunExe, bunEnv, isCI, isMusl } from "../../harness"; + +// Tests that intentionally abort and should not generate core dumps when they abort +// due to a Node-API error +const abortingJsNativeApiTests = ["test_finalizer/test_fatal_finalize.js"]; + +export async function build(dir: string) { + const child = spawn({ + cmd: [bunExe(), "x", "node-gyp@11", "rebuild", "--debug", "-j", "max", "--verbose"], + cwd: dir, + stderr: "pipe", + stdout: "ignore", + stdin: "inherit", + env: { + ...bunEnv, + npm_config_target: "v24.3.0", + CXXFLAGS: (bunEnv.CXXFLAGS ?? "") + (process.platform == "win32" ? " -std=c++20" : " -std=gnu++20"), + // on linux CI, node-gyp will default to g++ and the version installed there is very old, + // so we make it use clang instead + ...(process.platform == "linux" && isCI + ? { + CC: !isMusl ? "/usr/lib/llvm-19/bin/clang" : "/usr/lib/llvm19/bin/clang", + CXX: !isMusl ? "/usr/lib/llvm-19/bin/clang++" : "/usr/lib/llvm19/bin/clang++", + } + : {}), + }, + }); + await child.exited; + if (child.exitCode !== 0) { + const stderr = await new Response(child.stderr).text(); + console.error(`node-gyp rebuild in ${dir} failed:\n${stderr}`); + console.error("bailing out!"); + process.exit(1); + } +} + +export function run(dir: string, test: string) { + const env = abortingJsNativeApiTests.includes(test) + ? { ...bunEnv, BUN_INTERNAL_SUPPRESS_CRASH_ON_NAPI_ABORT: "1" } + : bunEnv; + const result = spawnSync({ + cmd: [bunExe(), "run", test], + cwd: dir, + stderr: "inherit", + stdout: "ignore", + stdin: "inherit", + env, + }); + expect(result.success).toBeTrue(); + expect(result.exitCode).toBe(0); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/2_function_arguments/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/2_function_arguments/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/2_function_arguments/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/3_callbacks/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/3_callbacks/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/3_callbacks/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/4_object_factory/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/4_object_factory/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/4_object_factory/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/5_function_factory/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/5_function_factory/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/5_function_factory/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/6_object_wrap/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/6_object_wrap/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/6_object_wrap/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/7_factory_wrap/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/7_factory_wrap/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/7_factory_wrap/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/8_passing_wrapped/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/8_passing_wrapped/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/8_passing_wrapped/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_array/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_array/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_array/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_bigint/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_bigint/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_bigint/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_cannot_run_js/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_cannot_run_js/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_cannot_run_js/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_constructor/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_constructor/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_constructor/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_conversions/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_conversions/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_conversions/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_dataview/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_dataview/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_dataview/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_date/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_date/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_date/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_error/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_error/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_error/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_exception/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_exception/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_exception/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_finalizer/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_finalizer/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_finalizer/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_function/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_function/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_function/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_general/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_general/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_general/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_handle_scope/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_handle_scope/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_handle_scope/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_instance_data/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_instance_data/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_instance_data/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_new_target/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_new_target/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_new_target/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_number/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_number/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_number/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_object/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_object/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_object/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_promise/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_promise/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_promise/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_properties/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_properties/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_properties/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_reference/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_reference/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_reference/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_reference_double_free/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_reference_double_free/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_reference_double_free/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_string/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_string/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_string/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_symbol/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_symbol/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_symbol/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/js-native-api/test_typedarray/do.test.ts b/test/napi/node-napi-tests/test/js-native-api/test_typedarray/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/js-native-api/test_typedarray/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/1_hello_world/do.test.ts b/test/napi/node-napi-tests/test/node-api/1_hello_world/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/1_hello_world/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_async/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_async/do.test.ts new file mode 100644 index 0000000000..51c297a34e --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_async/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js", "test-uncaught.js", "test-async-hooks.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_async_cleanup_hook/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_async_cleanup_hook/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_async_cleanup_hook/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_async_context/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_async_context/do.test.ts new file mode 100644 index 0000000000..ac1db5eff0 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_async_context/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js", "test-gcable.js", "test-gcable-callback.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_buffer/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_buffer/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_buffer/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_callback_scope/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_callback_scope/do.test.ts new file mode 100644 index 0000000000..a90189a571 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_callback_scope/do.test.ts @@ -0,0 +1,17 @@ +import { isWindows } from "harness"; +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + // https://github.com/oven-sh/bun/issues/12827 is the latter + test.todoIf(["test-resolve-async.js", "test-async-hooks.js"].includes(file) || (file === "test.js" && isWindows))( + file, + () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }, + ); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_cleanup_hook/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_cleanup_hook/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_cleanup_hook/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_env_teardown_gc/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_env_teardown_gc/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_env_teardown_gc/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_exception/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_exception/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_exception/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_fatal/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_fatal/do.test.ts new file mode 100644 index 0000000000..1df2bcca8d --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_fatal/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js", "test2.js", "test_threads.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_fatal_exception/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_fatal_exception/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_fatal_exception/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_general/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_general/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_general/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_init_order/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_init_order/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_init_order/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_instance_data/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_instance_data/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_instance_data/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_make_callback/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_make_callback/do.test.ts new file mode 100644 index 0000000000..236a69cd3c --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_make_callback/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test-async-hooks.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_make_callback_recurse/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_make_callback_recurse/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_make_callback_recurse/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_null_init/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_null_init/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_null_init/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_reference_by_node_api_version/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_reference_by_node_api_version/do.test.ts new file mode 100644 index 0000000000..3fb2958aff --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_reference_by_node_api_version/do.test.ts @@ -0,0 +1,13 @@ +import { isMacOS } from "harness"; +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file) && isMacOS)(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_threadsafe_function/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_threadsafe_function/do.test.ts new file mode 100644 index 0000000000..1dc9e903e8 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_threadsafe_function/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js", "test_legacy_uncaught_exception.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_uv_loop/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_uv_loop/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_uv_loop/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_uv_threadpool_size/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_uv_threadpool_size/do.test.ts new file mode 100644 index 0000000000..801ed71d31 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_uv_threadpool_size/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js", "node-options.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_worker_buffer_callback/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_worker_buffer_callback/do.test.ts new file mode 100644 index 0000000000..844863a945 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_worker_buffer_callback/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js", "test-free-called.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_worker_terminate/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_worker_terminate/do.test.ts new file mode 100644 index 0000000000..b35e011f23 --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_worker_terminate/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test.todoIf(["test.js"].includes(file))(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi-tests/test/node-api/test_worker_terminate_finalization/do.test.ts b/test/napi/node-napi-tests/test/node-api/test_worker_terminate_finalization/do.test.ts new file mode 100644 index 0000000000..727e5dc80a --- /dev/null +++ b/test/napi/node-napi-tests/test/node-api/test_worker_terminate_finalization/do.test.ts @@ -0,0 +1,12 @@ +import { basename, dirname, sep } from "node:path"; +import { build, run } from "../../../harness"; + +test("build", async () => { + await build(import.meta.dir); +}); + +for (const file of Array.from(new Bun.Glob("*.js").scanSync(import.meta.dir))) { + test(file, () => { + run(dirname(import.meta.dir), basename(import.meta.dir) + sep + file); + }); +} diff --git a/test/napi/node-napi.test.ts b/test/napi/node-napi.test.ts deleted file mode 100644 index 8b415a1a28..0000000000 --- a/test/napi/node-napi.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { Glob, spawn, spawnSync } from "bun"; -import { describe, expect, it } from "bun:test"; -import { bunEnv, bunExe, isBroken, isCI, isIntelMacOS, isMusl, isWindows } from "harness"; -import { dirname, join } from "path"; - -const jsNativeApiRoot = join(__dirname, "node-napi-tests", "test", "js-native-api"); -const nodeApiRoot = join(__dirname, "node-napi-tests", "test", "node-api"); - -const jsNativeApiTests = Array.from(new Glob("**/*.js").scanSync(jsNativeApiRoot)); -const nodeApiTests = Array.from(new Glob("**/*.js").scanSync(nodeApiRoot)); - -// These js-native-api tests are known to fail and will be fixed in later PRs -let failingJsNativeApiTests: string[] = [ - // We skip certain parts of test_string/test.js because we don't support creating empty external - // strings. We don't skip the entire thing because the other tests are useful to check. - // "test_string/test.js", -]; - -// These are the tests from node-api that failed as of commit 83f536f4d, except for those that -// passed in Bun v1.1.34. It'll take some time to get all these to work, as we've been focusing more -// on js-native-api tests so far, and we don't want these tests to pollute CI. But we do want to -// know if we regressed any of the other tests. -let failingNodeApiTests = [ - "test_uv_threadpool_size/test.js", - "test_uv_threadpool_size/node-options.js", - "test_uv_loop/test.js", - "test_callback_scope/test-resolve-async.js", - "test_callback_scope/test-async-hooks.js", - "test_fatal/test.js", - "test_fatal/test2.js", - "test_fatal/test_threads.js", - "test_threadsafe_function/test.js", - "test_threadsafe_function/test_legacy_uncaught_exception.js", - "test_worker_buffer_callback/test.js", - "test_worker_buffer_callback/test-free-called.js", // TODO(@heimskr) - "test_make_callback_recurse/test.js", - "test_buffer/test.js", - "test_instance_data/test.js", - "test_make_callback/test-async-hooks.js", - "test_async_context/test.js", - "test_async_context/test-gcable.js", - "test_async_context/test-gcable-callback.js", - "test_async_cleanup_hook/test.js", - "test_async/test.js", - "test_async/test-uncaught.js", - "test_async/test-async-hooks.js", - "test_general/test.js", - "test_env_teardown_gc/test.js", - "test_worker_terminate/test.js", -]; - -if (isBroken && isIntelMacOS) { - // TODO(@190n) - // these are flaky on Intel Mac - failingJsNativeApiTests.push("test_reference/test.js"); - failingNodeApiTests.push("test_reference_by_node_api_version/test.js"); -} - -if (isWindows) { - if (isBroken) { - failingNodeApiTests.push("test_callback_scope/test.js"); // TODO: remove once #12827 is fixed - } - - for (const i in failingJsNativeApiTests) { - failingJsNativeApiTests[i] = failingJsNativeApiTests[i].replaceAll("/", "\\"); - } - for (const i in failingNodeApiTests) { - failingNodeApiTests[i] = failingNodeApiTests[i].replaceAll("/", "\\"); - } -} - -if (isMusl) { - failingNodeApiTests = nodeApiTests; - failingJsNativeApiTests = jsNativeApiTests; -} - -// Tests that intentionally abort and should not generate core dumps when they abort -// due to a Node-API error -const abortingJsNativeApiTests = ["test_finalizer/test_fatal_finalize.js"]; - -for (const t of failingJsNativeApiTests) { - if (!jsNativeApiTests.includes(t)) { - console.error(`attempt to skip ${t} which is not a real js-native-api test`); - process.exit(1); - } -} -for (const t of failingNodeApiTests) { - if (!nodeApiTests.includes(t)) { - console.error(`attempt to skip ${t} which is not a real node-api test`); - process.exit(1); - } -} - -const directories = jsNativeApiTests - .filter(t => !failingJsNativeApiTests.includes(t)) - .map(t => join(jsNativeApiRoot, t)) - .concat(nodeApiTests.filter(t => !failingNodeApiTests.includes(t)).map(t => join(nodeApiRoot, t))) - .map(t => dirname(t)); -const uniqueDirectories = Array.from(new Set(directories)); - -describe("build", () => { - for (const dir of uniqueDirectories) { - it(`${dir.slice(import.meta.dir.length + 1)}`, async () => { - const child = spawn({ - cmd: [bunExe(), "x", "node-gyp@11", "rebuild", "--debug", "-j", "max"], - cwd: dir, - stderr: "pipe", - stdout: "ignore", - stdin: "inherit", - env: { - ...bunEnv, - npm_config_target: "v24.3.0", - CXXFLAGS: (bunEnv.CXXFLAGS ?? "") + (process.platform == "win32" ? " -std=c++20" : " -std=gnu++20"), - // on linux CI, node-gyp will default to g++ and the version installed there is very old, - // so we make it use clang instead - ...(process.platform == "linux" && isCI - ? { "CC": "/usr/lib/llvm-19/bin/clang", CXX: "/usr/lib/llvm-19/bin/clang++" } - : {}), - }, - }); - await child.exited; - if (child.exitCode !== 0) { - const stderr = await new Response(child.stderr).text(); - console.error(`node-gyp rebuild in ${dir} failed:\n${stderr}`); - console.error("bailing out!"); - process.exit(1); - } - }); - } -}); - -describe("js-native-api tests", () => { - for (const test of jsNativeApiTests) { - describe.skipIf(failingJsNativeApiTests.includes(test))(`${test}`, () => { - it("passes", () => { - const env = abortingJsNativeApiTests.includes(test) - ? { ...bunEnv, BUN_INTERNAL_SUPPRESS_CRASH_ON_NAPI_ABORT: "1" } - : bunEnv; - const result = spawnSync({ - cmd: [bunExe(), "run", test], - cwd: jsNativeApiRoot, - stderr: "inherit", - stdout: "ignore", - stdin: "inherit", - env, - }); - expect(result.success).toBeTrue(); - expect(result.exitCode).toBe(0); - }, 60_000); - }); - } -}); - -describe("node-api tests", () => { - for (const test of nodeApiTests) { - describe.skipIf(failingNodeApiTests.includes(test))(`${test}`, () => { - it("passes", () => { - const result = spawnSync({ - cmd: [bunExe(), "run", test], - cwd: nodeApiRoot, - stderr: "inherit", - stdout: "ignore", - stdin: "inherit", - env: bunEnv, - }); - expect(result.success).toBeTrue(); - expect(result.exitCode).toBe(0); - }, 60_000); - }); - } -}); diff --git a/test/no-validate-exceptions.txt b/test/no-validate-exceptions.txt index 0e166286a7..8bdb9db4ee 100644 --- a/test/no-validate-exceptions.txt +++ b/test/no-validate-exceptions.txt @@ -200,6 +200,7 @@ test/cli/install/isolated-install.test.ts test/cli/install/bun-publish.test.ts test/cli/install/bun-lock.test.ts test/cli/install/bun-install-lifecycle-scripts.test.ts +test/cli/update_interactive_formatting.test.ts # ProgramExecutable::initializeGlobalProperties # missing RELEASE_AND_RETURN test/js/node/test/parallel/test-repl-syntax-error-handling.js @@ -252,9 +253,39 @@ test/js/third_party/prisma/prisma.test.ts test/js/third_party/remix/remix.test.ts test/js/third_party/resvg/bbox.test.js test/js/third_party/rollup-v4/rollup-v4.test.ts -test/napi/node-napi.test.ts test/napi/uv.test.ts test/napi/uv_stub.test.ts +test/napi/node-napi-tests/test/js-native-api/2_function_arguments/do.test.ts +test/napi/node-napi-tests/test/js-native-api/3_callbacks/do.test.ts +test/napi/node-napi-tests/test/js-native-api/4_object_factory/do.test.ts +test/napi/node-napi-tests/test/js-native-api/5_function_factory/do.test.ts +test/napi/node-napi-tests/test/js-native-api/6_object_wrap/do.test.ts +test/napi/node-napi-tests/test/js-native-api/7_factory_wrap/do.test.ts +test/napi/node-napi-tests/test/js-native-api/8_passing_wrapped/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_array/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_bigint/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_cannot_run_js/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_constructor/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_conversions/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_dataview/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_date/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_error/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_function/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_handle_scope/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_instance_data/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_new_target/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_number/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_object/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_promise/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_reference_double_free/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_symbol/do.test.ts +test/napi/node-napi-tests/test/js-native-api/test_typedarray/do.test.ts +test/napi/node-napi-tests/test/node-api/1_hello_world/do.test.ts +test/napi/node-napi-tests/test/node-api/test_async/do.test.ts +test/napi/node-napi-tests/test/node-api/test_cleanup_hook/do.test.ts +test/napi/node-napi-tests/test/node-api/test_exception/do.test.ts +test/napi/node-napi-tests/test/node-api/test_fatal_exception/do.test.ts +test/napi/node-napi-tests/test/node-api/test_worker_terminate_finalization/do.test.ts # normalizeCryptoAlgorithmParameters test/js/node/test/parallel/test-webcrypto-derivekey.js diff --git a/test/package.json b/test/package.json index 7eac577d26..7b82632372 100644 --- a/test/package.json +++ b/test/package.json @@ -52,6 +52,7 @@ "http2-wrapper": "2.2.1", "https-proxy-agent": "7.0.5", "iconv-lite": "0.6.3", + "immutable": "5.1.3", "isbot": "5.1.13", "jest-extended": "4.0.0", "jimp": "1.6.0", @@ -95,7 +96,7 @@ "tsyringe": "4.8.0", "type-graphql": "2.0.0-rc.2", "typeorm": "0.3.20", - "typescript": "5.8.3", + "typescript": "5.9.2", "undici": "5.20.0", "unzipper": "0.12.3", "uuid": "11.1.0", diff --git a/test/regression/issue/10380/spy-matchers-diff.test.ts b/test/regression/issue/10380/spy-matchers-diff.test.ts new file mode 100644 index 0000000000..326d26a378 --- /dev/null +++ b/test/regression/issue/10380/spy-matchers-diff.test.ts @@ -0,0 +1,127 @@ +import { expect, mock, test } from "bun:test"; + +test("toHaveBeenCalledWith should show diff when assertion fails", () => { + const mockedFn = mock(args => args); + + const a = { a: { b: { c: { d: 1 } } } }; + const b = { a: { b: { c: { d: 2 } } } }; + + mockedFn(a); + + let error: Error | undefined; + try { + expect(mockedFn).toHaveBeenCalledWith(b); + } catch (e) { + error = e as Error; + } + + expect(error).toBeDefined(); + expect(error!.message).toContain("- Expected"); + expect(error!.message).toContain("+ Received"); + expect(error!.message).toContain("d: 1"); + expect(error!.message).toContain("d: 2"); +}); + +test("toHaveBeenNthCalledWith should show diff when assertion fails", () => { + const mockedFn = mock(args => args); + + const a = { x: [1, 2, 3] }; + const b = { x: [1, 2, 4] }; + + mockedFn(a); + + let error: Error | undefined; + try { + expect(mockedFn).toHaveBeenNthCalledWith(1, b); + } catch (e) { + error = e as Error; + } + + expect(error).toBeDefined(); + expect(error!.message).toContain("- Expected"); + expect(error!.message).toContain("+ Received"); +}); + +test("toHaveBeenLastCalledWith should show diff when assertion fails", () => { + const mockedFn = mock(args => args); + + const a = { nested: { value: "hello" } }; + const b = { nested: { value: "world" } }; + + mockedFn("first"); + mockedFn(a); + + let error: Error | undefined; + try { + expect(mockedFn).toHaveBeenLastCalledWith(b); + } catch (e) { + error = e as Error; + } + + expect(error).toBeDefined(); + expect(error!.message).toContain("- Expected"); + expect(error!.message).toContain("+ Received"); + expect(error!.message).toContain("hello"); + expect(error!.message).toContain("world"); +}); + +test("toHaveBeenCalledWith should show diff for multiple arguments", () => { + const mockedFn = mock((a, b, c) => [a, b, c]); + + mockedFn(1, { foo: "bar" }, [1, 2, 3]); + + let error: Error | undefined; + try { + expect(mockedFn).toHaveBeenCalledWith(1, { foo: "baz" }, [1, 2, 4]); + } catch (e) { + error = e as Error; + } + + expect(error).toBeDefined(); + expect(error!.message).toContain("- Expected"); + expect(error!.message).toContain("+ Received"); + expect(error!.message).toContain("bar"); + expect(error!.message).toContain("baz"); +}); + +test("toHaveBeenCalledWith should show diff for complex nested structures", () => { + const mockedFn = mock(args => args); + + const received = { + users: [ + { id: 1, name: "Alice", roles: ["admin", "user"] }, + { id: 2, name: "Bob", roles: ["user"] }, + ], + settings: { + theme: "dark", + notifications: { email: true, push: false }, + }, + }; + + const expected = { + users: [ + { id: 1, name: "Alice", roles: ["admin", "user"] }, + { id: 2, name: "Bob", roles: ["moderator", "user"] }, + ], + settings: { + theme: "light", + notifications: { email: true, push: false }, + }, + }; + + mockedFn(received); + + let error: Error | undefined; + try { + expect(mockedFn).toHaveBeenCalledWith(expected); + } catch (e) { + error = e as Error; + } + + expect(error).toBeDefined(); + expect(error!.message).toContain("- Expected"); + expect(error!.message).toContain("+ Received"); + expect(error!.message).toContain("dark"); + expect(error!.message).toContain("light"); + expect(error!.message).toContain("moderator"); +}); diff --git a/test/regression/issue/18820.test.ts b/test/regression/issue/18820.test.ts new file mode 100644 index 0000000000..628163f6fb --- /dev/null +++ b/test/regression/issue/18820.test.ts @@ -0,0 +1,24 @@ +import { expect, mock, test } from "bun:test"; + +const random1 = mock(() => Math.random()); +const random2 = mock(() => Math.random()); + +test("clearing all mocks", () => { + random1(); + random2(); + + expect(random1).toHaveBeenCalledTimes(1); + expect(random2).toHaveBeenCalledTimes(1); + + mock.clearAllMocks(); + + expect(random1).toHaveBeenCalledTimes(0); + expect(random2).toHaveBeenCalledTimes(0); + + // Note: implementations are preserved + expect(typeof random1()).toBe("number"); + expect(typeof random2()).toBe("number"); + + expect(random1).toHaveBeenCalledTimes(1); + expect(random2).toHaveBeenCalledTimes(1); +});