diff --git a/.buildkite/ci.mjs b/.buildkite/ci.mjs index 3fb1e643f32f31..98506933dee565 100755 --- a/.buildkite/ci.mjs +++ b/.buildkite/ci.mjs @@ -462,6 +462,7 @@ function getBuildZigStep(platform, options) { cancel_on_build_failing: isMergeQueue(), env: getBuildEnv(platform, options), command: `bun run build:ci --target bun-zig --toolchain ${toolchain}`, + timeout_in_minutes: 25, }; } diff --git a/.cursor/rules/javascriptcore-class.mdc b/.cursor/rules/javascriptcore-class.mdc new file mode 100644 index 00000000000000..6a6ebc6498c9e8 --- /dev/null +++ b/.cursor/rules/javascriptcore-class.mdc @@ -0,0 +1,378 @@ +--- +description: JavaScript class implemented in C++ +globs: *.cpp +--- + +# Implementing JavaScript classes in C++ + +If there is a publicly accessible Constructor and Prototype, then there are 3 classes: + +- IF there are C++ class members we need a destructor, so `class Foo : public JSC::DestructibleObject`, if no C++ class fields (only JS properties) then we don't need a class at all usually. We can instead use JSC::constructEmptyObject(vm, structure) and `putDirectOffset` like in [NodeFSBinding.cpp](mdc:src/bun.js/bindings/NodeFSBinding.cpp). +- class FooPrototype : public JSC::JSNonFinalObject +- class FooConstructor : public JSC::InternalFunction + +If there is no publicly accessible Constructor, just the Prototype and the class is necessary. In some cases, we can avoid the prototype entirely (but that's rare). + +If there are C++ fields on the Foo class, the Foo class will need an iso subspace added to [DOMClientIsoSubspaces.h](mdc:src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h) and [DOMIsoSubspaces.h](mdc:src/bun.js/bindings/webcore/DOMIsoSubspaces.h). Prototype and Constructor do not need subspaces. + +Usually you'll need to #include "root.h" at the top of C++ files or you'll get lint errors. + +Generally, defining the subspace looks like this: +```c++ + +class Foo : public JSC::DestructibleObject { + +// ... + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceFor${MyClassT}.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceFor${MyClassT} = std::forward(space); }, + [](auto& spaces) { return spaces.m_subspaceFo${MyClassT}.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceFor${MyClassT} = std::forward(space); }); + } + + +``` + +It's better to put it in the .cpp file instead of the .h file, when possible. + +## Defining properties + +Define properties on the prototype. Use a const HashTableValues like this: +```C++ +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckEmail); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckHost); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIP); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckIssued); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncCheckPrivateKey); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToJSON); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToLegacyObject); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncToString); +static JSC_DECLARE_HOST_FUNCTION(jsX509CertificateProtoFuncVerify); + +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_ca); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint256); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_fingerprint512); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_subject); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_subjectAltName); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_infoAccess); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_keyUsage); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_issuer); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_issuerCertificate); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_publicKey); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_raw); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_serialNumber); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validFrom); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validTo); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validFromDate); +static JSC_DECLARE_CUSTOM_GETTER(jsX509CertificateGetter_validToDate); + +static const HashTableValue JSX509CertificatePrototypeTableValues[] = { + { "ca"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_ca, 0 } }, + { "checkEmail"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckEmail, 2 } }, + { "checkHost"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckHost, 2 } }, + { "checkIP"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckIP, 1 } }, + { "checkIssued"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckIssued, 1 } }, + { "checkPrivateKey"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncCheckPrivateKey, 1 } }, + { "fingerprint"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint, 0 } }, + { "fingerprint256"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint256, 0 } }, + { "fingerprint512"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_fingerprint512, 0 } }, + { "infoAccess"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_infoAccess, 0 } }, + { "issuer"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_issuer, 0 } }, + { "issuerCertificate"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_issuerCertificate, 0 } }, + { "keyUsage"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_keyUsage, 0 } }, + { "publicKey"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_publicKey, 0 } }, + { "raw"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_raw, 0 } }, + { "serialNumber"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_serialNumber, 0 } }, + { "subject"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_subject, 0 } }, + { "subjectAltName"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_subjectAltName, 0 } }, + { "toJSON"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToJSON, 0 } }, + { "toLegacyObject"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToLegacyObject, 0 } }, + { "toString"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncToString, 0 } }, + { "validFrom"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validFrom, 0 } }, + { "validFromDate"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validFromDate, 0 } }, + { "validTo"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validTo, 0 } }, + { "validToDate"_s, static_cast(PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue), NoIntrinsic, { HashTableValue::GetterSetterType, jsX509CertificateGetter_validToDate, 0 } }, + { "verify"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsX509CertificateProtoFuncVerify, 1 } }, +}; +``` + +### Creating a prototype class + +Follow a pattern like this: + +```c++ +class JSX509CertificatePrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSX509CertificatePrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSX509CertificatePrototype* prototype = new (NotNull, allocateCell(vm)) JSX509CertificatePrototype(vm, structure); + prototype->finishCreation(vm); + return prototype; + } + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + auto* structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + structure->setMayBePrototype(true); + return structure; + } + +private: + JSX509CertificatePrototype(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM& vm); +}; + +const ClassInfo JSX509CertificatePrototype::s_info = { "X509Certificate"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSX509CertificatePrototype) }; + +void JSX509CertificatePrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSX509Certificate::info(), JSX509CertificatePrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +} // namespace Bun +``` + +### Getter definition: +```C++ + +JSC_DEFINE_CUSTOM_GETTER(jsX509CertificateGetter_ca, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSX509Certificate* thisObject = jsDynamicCast(JSValue::decode(thisValue)); + if (UNLIKELY(!thisObject)) { + Bun::throwThisTypeError(*globalObject, scope, "JSX509Certificate"_s, "ca"_s); + return {}; + } + + return JSValue::encode(jsBoolean(thisObject->view().isCA())); +} +``` + +### Setter definition + +```C++ +JSC_DEFINE_CUSTOM_SETTER(jsImportMetaObjectSetter_require, (JSGlobalObject * jsGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, PropertyName propertyName)) +{ + ImportMetaObject* thisObject = jsDynamicCast(JSValue::decode(thisValue)); + if (UNLIKELY(!thisObject)) + return false; + + JSValue value = JSValue::decode(encodedValue); + if (!value.isCell()) { + // TODO: + return true; + } + + thisObject->requireProperty.set(thisObject->vm(), thisObject, value.asCell()); + return true; +} +``` + +### Function definition + +```C++ +JSC_DEFINE_HOST_FUNCTION(jsX509CertificateProtoFuncToJSON, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + auto *thisObject = jsDynamicCast(callFrame->thisValue()); + if (UNLIKELY(!thisObject)) { + Bun::throwThisTypeError(*globalObject, scope, "MyClass"_s, "myFunctionName"_s); + return {}; + } + + return JSValue::encode(functionThatReturnsJSValue(vm, globalObject, thisObject)); +} +``` + + +### Constructor definition + +```C++ + +JSC_DECLARE_HOST_FUNCTION(callStats); +JSC_DECLARE_HOST_FUNCTION(constructStats); + +class JSStatsConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSStatsConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* prototype) + { + JSStatsConstructor* constructor = new (NotNull, JSC::allocateCell(vm)) JSStatsConstructor(vm, structure); + constructor->finishCreation(vm, prototype); + return constructor; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.internalFunctionSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + +private: + JSStatsConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, callStats, constructStats) + { + } + + void finishCreation(JSC::VM& vm, JSC::JSObject* prototype) + { + Base::finishCreation(vm, 0, "Stats"_s); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + } +}; +``` + + +### Structure caching + +If there's a class, prototype, and constructor: + +1. Add the `JSC::LazyClassStructure` to [ZigGlobalObject.h](mdc:src/bun.js/bindings/ZigGlobalObject.h) +2. Initialize the class structure in [ZigGlobalObject.cpp](mdc:src/bun.js/bindings/ZigGlobalObject.cpp) in `void GlobalObject::finishCreation(VM& vm)` +3. Visit the class structure in visitChildren in [ZigGlobalObject.cpp](mdc:src/bun.js/bindings/ZigGlobalObject.cpp) in `void GlobalObject::visitChildrenImpl` + +```c++ + + m_JSStatsBigIntClassStructure.initLater( + [](LazyClassStructure::Initializer& init) { + Bun::initJSBigIntStatsClassStructure(init); + }); +``` + +If there's only a class, use `JSC::LazyProperty` instead of `JSC::LazyClassStructure`. + +Then, implement the function that creates the structure: +```c++ +void setupX509CertificateClassStructure(LazyClassStructure::Initializer& init) +{ + auto* prototypeStructure = JSX509CertificatePrototype::createStructure(init.vm, init.global, init.global->objectPrototype()); + auto* prototype = JSX509CertificatePrototype::create(init.vm, init.global, prototypeStructure); + + auto* constructorStructure = JSX509CertificateConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()); + + auto* constructor = JSX509CertificateConstructor::create(init.vm, init.global, constructorStructure, prototype); + + auto* structure = JSX509Certificate::createStructure(init.vm, init.global, prototype); + init.setPrototype(prototype); + init.setStructure(structure); + init.setConstructor(constructor); +} +``` + +Then, use the structure by calling `globalObject.m_myStructureName.get(globalObject)` + +```C++ +JSC_DEFINE_HOST_FUNCTION(x509CertificateConstructorConstruct, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!callFrame->argumentCount()) { + Bun::throwError(globalObject, scope, ErrorCode::ERR_MISSING_ARGS, "X509Certificate constructor requires at least one argument"_s); + return {}; + } + + JSValue arg = callFrame->uncheckedArgument(0); + if (!arg.isCell()) { + Bun::throwError(globalObject, scope, ErrorCode::ERR_INVALID_ARG_TYPE, "X509Certificate constructor argument must be a Buffer, TypedArray, or string"_s); + return {}; + } + + auto* zigGlobalObject = defaultGlobalObject(globalObject); + Structure* structure = zigGlobalObject->m_JSX509CertificateClassStructure.get(zigGlobalObject); + JSValue newTarget = callFrame->newTarget(); + if (UNLIKELY(zigGlobalObject->m_JSX509CertificateClassStructure.constructor(zigGlobalObject) != newTarget)) { + auto scope = DECLARE_THROW_SCOPE(vm); + if (!newTarget) { + throwTypeError(globalObject, scope, "Class constructor X509Certificate cannot be invoked without 'new'"_s); + return {}; + } + + auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); + RETURN_IF_EXCEPTION(scope, {}); + structure = InternalFunction::createSubclassStructure( + globalObject, newTarget.getObject(), functionGlobalObject->NodeVMScriptStructure()); + scope.release(); + } + + return JSValue::encode(createX509Certificate(vm, globalObject, structure, arg)); +} +``` + +### Expose to Zig + +To expose the constructor to zig: + +```c++ +extern "C" JSC::EncodedJSValue Bun__JSBigIntStatsObjectConstructor(Zig::GlobalObject* globalobject) +{ + return JSValue::encode(globalobject->m_JSStatsBigIntClassStructure.constructor(globalobject)); +} +``` + +Zig: +```zig +extern "c" fn Bun__JSBigIntStatsObjectConstructor(*JSC.JSGlobalObject) JSC.JSValue; +pub const getBigIntStatsConstructor = Bun__JSBigIntStatsObjectConstructor; +``` + +To create an object (instance) of a JS class defined in C++ from Zig, follow the __toJS convention like this: +```c++ +// X509* is whatever we need to create the object +extern "C" EncodedJSValue Bun__X509__toJS(Zig::GlobalObject* globalObject, X509* cert) +{ + // ... implementation details + auto* structure = globalObject->m_JSX509CertificateClassStructure.get(globalObject); + return JSValue::encode(JSX509Certificate::create(globalObject->vm(), structure, globalObject, WTFMove(cert))); +} +``` + +And from Zig: +```zig +const X509 = opaque { + // ... class + + extern fn Bun__X509__toJS(*JSC.JSGlobalObject, *X509) JSC.JSValue; + + pub fn toJS(this: *X509, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + return Bun__X509__toJS(globalObject, this); + } +}; +``` diff --git a/.gitattributes b/.gitattributes index 1b3908f258f862..bc089ec2f34a70 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,6 +15,7 @@ *.lock text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 *.map text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 *.md text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.mdc text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 *.mjs text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 *.mts text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml index 0e6e6103c89855..d8d2745c170fd5 100644 --- a/.github/actions/setup-bun/action.yml +++ b/.github/actions/setup-bun/action.yml @@ -4,7 +4,7 @@ description: An internal version of the 'oven-sh/setup-bun' action. inputs: bun-version: type: string - description: "The version of bun to install: 'latest', 'canary', 'bun-v1.0.0', etc." + description: "The version of bun to install: 'latest', 'canary', 'bun-v1.2.0', etc." default: latest required: false baseline: diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 8eff85a4291f6a..be833ae846a888 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -10,7 +10,7 @@ on: merge_group: env: - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" LLVM_VERSION: "18.1.8" LLVM_VERSION_MAJOR: "18" diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 2d0aab1021edd4..934af25254847c 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -10,7 +10,7 @@ on: merge_group: env: - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" LLVM_VERSION: "18.1.8" LLVM_VERSION_MAJOR: "18" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 593a77b115a2ed..33ef015a534284 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,7 +5,7 @@ on: workflow_dispatch: env: - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" OXLINT_VERSION: "0.15.0" jobs: diff --git a/.github/workflows/prettier-format.yml b/.github/workflows/prettier-format.yml index 67a1c96afbab15..8f0c127202f1b9 100644 --- a/.github/workflows/prettier-format.yml +++ b/.github/workflows/prettier-format.yml @@ -10,7 +10,7 @@ on: merge_group: env: - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" jobs: prettier-format: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 904c6a7b271239..ed68ab8c90856c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,6 +44,10 @@ on: description: Should types be released to npm? type: boolean default: false + use-definitelytyped: + description: "Should types be PR'd to DefinitelyTyped?" + type: boolean + default: false jobs: sign: @@ -66,7 +70,7 @@ jobs: - name: Setup Bun uses: ./.github/actions/setup-bun with: - bun-version: "1.1.44" + bun-version: "1.2.0" - name: Install Dependencies run: bun install - name: Sign Release @@ -94,7 +98,7 @@ jobs: - name: Setup Bun uses: ./.github/actions/setup-bun with: - bun-version: "1.1.44" + bun-version: "1.2.0" - name: Install Dependencies run: bun install - name: Release @@ -123,7 +127,7 @@ jobs: if: ${{ env.BUN_VERSION != 'canary' }} uses: ./.github/actions/setup-bun with: - bun-version: "1.1.44" + bun-version: "1.2.0" - name: Setup Bun if: ${{ env.BUN_VERSION == 'canary' }} uses: ./.github/actions/setup-bun @@ -155,6 +159,48 @@ jobs: with: package: packages/bun-types/package.json token: ${{ secrets.NPM_TOKEN }} + definitelytyped: + name: Make pr to DefinitelyTyped to update `bun-types` version + runs-on: ubuntu-latest + needs: npm-types + if: ${{ github.event_name == 'release' || github.event.inputs.use-definitelytyped == 'true' }} + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + repository: DefinitelyTyped/DefinitelyTyped + - name: Setup Bun + uses: ./.github/actions/setup-bun + with: + bun-version: "1.2.0" + - id: bun-version + run: echo "BUN_VERSION=${BUN_VERSION#bun-v}" >> "$GITHUB_OUTPUT" + - name: Update bun-types version in package.json + run: | + bun -e ' + const file = Bun.file("./types/bun/package.json"); + const json = await file.json(); + const version = "${{ steps.bun-version.outputs.BUN_VERSION }}"; + json.dependencies["bun-types"] = version; + json.version = version.slice(0, version.lastIndexOf(".")) + ".9999"; + await file.write(JSON.stringify(json, null, 4) + "\n"); + ' + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + if: ${{ env.BUN_LATEST == 'true' && env.BUN_VERSION != 'canary'}} + with: + token: ${{ secrets.ROBOBUN_TOKEN }} + add-paths: ./types/bun/package.json + title: "[bun] update to ${{ steps.bun-version.outputs.BUN_VERSION }}" + commit-message: "[bun] update to ${{ steps.bun-version.outputs.BUN_VERSION }}" + body: | + Update `bun-types` version to ${{ steps.bun-version.outputs.BUN_VERSION }} + + https://bun.sh/blog/${{ env.BUN_VERSION }} + push-to-fork: oven-sh/DefinitelyTyped + branch: ${{env.BUN_VERSION}} docker: name: Release to Dockerhub runs-on: ubuntu-latest @@ -265,7 +311,7 @@ jobs: - name: Setup Bun uses: ./.github/actions/setup-bun with: - bun-version: "1.1.44" + bun-version: "1.2.0" - name: Install Dependencies run: bun install - name: Release @@ -309,7 +355,7 @@ jobs: uses: ./.github/actions/setup-bun if: ${{ env.BUN_LATEST == 'true' }} with: - bun-version: "1.1.44" + bun-version: "1.2.0" - name: Bump version uses: ./.github/actions/bump if: ${{ env.BUN_LATEST == 'true' }} diff --git a/.github/workflows/run-lint.yml b/.github/workflows/run-lint.yml index 5ce9a19050e9ba..648da1a9cae371 100644 --- a/.github/workflows/run-lint.yml +++ b/.github/workflows/run-lint.yml @@ -4,7 +4,7 @@ permissions: contents: read env: LLVM_VERSION: 16 - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" on: workflow_call: diff --git a/.github/workflows/test-bump.yml b/.github/workflows/test-bump.yml index 7c8d9e57ef24f2..e2a4ae1b0508b2 100644 --- a/.github/workflows/test-bump.yml +++ b/.github/workflows/test-bump.yml @@ -9,7 +9,7 @@ on: required: true env: - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" jobs: bump: diff --git a/.github/workflows/zig-format.yml b/.github/workflows/zig-format.yml index 1649a67c60576d..199ab83395f675 100644 --- a/.github/workflows/zig-format.yml +++ b/.github/workflows/zig-format.yml @@ -10,7 +10,7 @@ on: merge_group: env: - BUN_VERSION: "1.1.44" + BUN_VERSION: "1.2.0" jobs: zig-format: diff --git a/.gitignore b/.gitignore index af3120ab439e4e..b791b8bc3a047f 100644 --- a/.gitignore +++ b/.gitignore @@ -151,6 +151,7 @@ src/bake/generated.ts test/cli/install/registry/packages/publish-pkg-* test/cli/install/registry/packages/@secret/publish-pkg-8 test/js/third_party/prisma/prisma/sqlite/dev.db-journal +tmp # Dependencies /vendor @@ -178,4 +179,4 @@ test/js/third_party/prisma/prisma/sqlite/dev.db-journal .buildkite/ci.yml *.sock -scratch*.{js,ts,tsx,cjs,mjs} \ No newline at end of file +scratch*.{js,ts,tsx,cjs,mjs} diff --git a/.prettierignore b/.prettierignore index 42d0c454a9c4ae..5344afdbd84b1c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,4 @@ src/react-refresh.js *.min.js test/snippets test/js/node/test +bun.lock diff --git a/.vscode/settings.json b/.vscode/settings.json index eca14849b66fe7..f7f738011685e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -140,6 +140,7 @@ }, "files.associations": { "*.idl": "cpp", + "*.mdc": "markdown", "array": "cpp", }, "C_Cpp.files.exclude": { diff --git a/LATEST b/LATEST index 867e52437ab800..d2d61a7e8e4372 100644 --- a/LATEST +++ b/LATEST @@ -1 +1 @@ -1.2.0 \ No newline at end of file +1.2.2 \ No newline at end of file diff --git a/Makefile b/Makefile index f1a8be26462ff0..d2940c28196f95 100644 --- a/Makefile +++ b/Makefile @@ -91,9 +91,9 @@ ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make # This is easier to happen than you'd expect. # Using realpath here causes issues because clang uses clang++ as a symlink # so if that's resolved, it won't build for C++ -REAL_CC = $(shell which clang-16 2>/dev/null || which clang 2>/dev/null) -REAL_CXX = $(shell which clang++-16 2>/dev/null || which clang++ 2>/dev/null) -CLANG_FORMAT = $(shell which clang-format-16 2>/dev/null || which clang-format 2>/dev/null) +REAL_CC = $(shell which clang-18 2>/dev/null || which clang 2>/dev/null) +REAL_CXX = $(shell which clang++-18 2>/dev/null || which clang++ 2>/dev/null) +CLANG_FORMAT = $(shell which clang-format-18 2>/dev/null || which clang-format 2>/dev/null) CC = $(REAL_CC) CXX = $(REAL_CXX) @@ -117,14 +117,14 @@ CC_WITH_CCACHE = $(CCACHE_PATH) $(CC) ifeq ($(OS_NAME),darwin) # Find LLVM ifeq ($(wildcard $(LLVM_PREFIX)),) - LLVM_PREFIX = $(shell brew --prefix llvm@16) + LLVM_PREFIX = $(shell brew --prefix llvm@18) endif ifeq ($(wildcard $(LLVM_PREFIX)),) LLVM_PREFIX = $(shell brew --prefix llvm) endif ifeq ($(wildcard $(LLVM_PREFIX)),) # This is kinda ugly, but I can't find a better way to error :( - LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@16' or set LLVM_PREFIX=/path/to/llvm") + LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@18' or set LLVM_PREFIX=/path/to/llvm") endif LDFLAGS += -L$(LLVM_PREFIX)/lib @@ -164,7 +164,7 @@ CMAKE_FLAGS_WITHOUT_RELEASE = -DCMAKE_C_COMPILER=$(CC) \ -DCMAKE_OSX_DEPLOYMENT_TARGET=$(MIN_MACOS_VERSION) \ $(CMAKE_CXX_COMPILER_LAUNCHER_FLAG) \ -DCMAKE_AR=$(AR) \ - -DCMAKE_RANLIB=$(which llvm-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \ + -DCMAKE_RANLIB=$(which llvm-18-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) \ -DCMAKE_CXX_STANDARD=20 \ -DCMAKE_C_STANDARD=17 \ -DCMAKE_CXX_STANDARD_REQUIRED=ON \ @@ -191,7 +191,7 @@ endif ifeq ($(OS_NAME),linux) LIBICONV_PATH = -AR = $(shell which llvm-ar-16 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null) +AR = $(shell which llvm-ar-18 2>/dev/null || which llvm-ar 2>/dev/null || which ar 2>/dev/null) endif OPTIMIZATION_LEVEL=-O3 $(MARCH_NATIVE) @@ -286,7 +286,7 @@ STRIP=/usr/bin/strip endif ifeq ($(OS_NAME),linux) -STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-16 2>/dev/null || which strip 2>/dev/null || echo "Missing strip") +STRIP=$(shell which llvm-strip 2>/dev/null || which llvm-strip-18 2>/dev/null || which strip 2>/dev/null || echo "Missing strip") endif @@ -674,7 +674,7 @@ endif .PHONY: assert-deps assert-deps: @echo "Checking if the required utilities are available..." - @if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@16"; exit 1; fi + @if [ $(CLANG_VERSION) -lt "18" ]; then echo -e "ERROR: clang version >=18 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@18"; exit 1; fi @cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1) @$(PYTHON) --version >/dev/null 2>&1 || (echo -e "ERROR: python is required."; exit 1) @$(ESBUILD) --version >/dev/null 2>&1 || (echo -e "ERROR: esbuild is required."; exit 1) @@ -1261,6 +1261,7 @@ jsc-build-mac-compile: -DBUN_FAST_TLS=ON \ -DENABLE_FTL_JIT=ON \ -DUSE_BUN_JSC_ADDITIONS=ON \ + -DUSE_BUN_EVENT_LOOP=ON \ -G Ninja \ $(CMAKE_FLAGS_WITHOUT_RELEASE) \ -DPTHREAD_JIT_PERMISSIONS_API=1 \ @@ -1284,6 +1285,7 @@ jsc-build-mac-compile-lto: -DUSE_THIN_ARCHIVES=OFF \ -DBUN_FAST_TLS=ON \ -DUSE_BUN_JSC_ADDITIONS=ON \ + -DUSE_BUN_EVENT_LOOP=ON \ -DCMAKE_C_FLAGS="-flto=full" \ -DCMAKE_CXX_FLAGS="-flto=full" \ -DENABLE_FTL_JIT=ON \ @@ -1310,6 +1312,7 @@ jsc-build-mac-compile-debug: -DENABLE_MALLOC_HEAP_BREAKDOWN=ON \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DUSE_BUN_JSC_ADDITIONS=ON \ + -DUSE_BUN_EVENT_LOOP=ON \ -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \ -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \ -G Ninja \ @@ -1334,6 +1337,7 @@ jsc-build-linux-compile-config: -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \ -DUSE_THIN_ARCHIVES=OFF \ -DUSE_BUN_JSC_ADDITIONS=ON \ + -DUSE_BUN_EVENT_LOOP=ON \ -DENABLE_FTL_JIT=ON \ -DENABLE_REMOTE_INSPECTOR=ON \ -DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \ @@ -1357,6 +1361,7 @@ jsc-build-linux-compile-config-debug: -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \ -DUSE_THIN_ARCHIVES=OFF \ -DUSE_BUN_JSC_ADDITIONS=ON \ + -DUSE_BUN_EVENT_LOOP=ON \ -DENABLE_FTL_JIT=ON \ -DENABLE_REMOTE_INSPECTOR=ON \ -DJSEXPORT_PRIVATE=WTF_EXPORT_DECLARATION \ @@ -1375,14 +1380,14 @@ jsc-build-linux-compile-config-debug: jsc-build-linux-compile-build: mkdir -p $(WEBKIT_RELEASE_DIR) && \ cd $(WEBKIT_RELEASE_DIR) && \ - CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \ + CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON" \ cmake --build $(WEBKIT_RELEASE_DIR) --config relwithdebuginfo --target jsc .PHONY: jsc-build-linux-compile-build-debug jsc-build-linux-compile-build-debug: mkdir -p $(WEBKIT_DEBUG_DIR) && \ cd $(WEBKIT_DEBUG_DIR) && \ - CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON" \ + CFLAGS="$(CFLAGS) -Wl,--whole-archive -ffat-lto-objects" CXXFLAGS="$(CXXFLAGS) -Wl,--whole-archive -ffat-lto-objects -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON" \ cmake --build $(WEBKIT_DEBUG_DIR) --config Debug --target jsc diff --git a/bench/bun.lock b/bench/bun.lock index cba2c6b04c39c8..31e497f2fa8c5e 100644 --- a/bench/bun.lock +++ b/bench/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bench", diff --git a/bench/expect-to-equal/bun.lock b/bench/expect-to-equal/bun.lock index 19f96c777ce82a..581a1739749521 100644 --- a/bench/expect-to-equal/bun.lock +++ b/bench/expect-to-equal/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "expect-to-equal", @@ -136,7 +136,7 @@ "@jest/console": ["@jest/console@29.4.3", "", { "dependencies": { "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "slash": "^3.0.0" } }, "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A=="], - "@jest/core": ["@jest/core@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/reporters": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.4.3", "jest-config": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-message-util": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-resolve-dependencies": "^29.4.3", "jest-runner": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" } }, "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ=="], + "@jest/core": ["@jest/core@29.4.3", "", { "dependencies": { "@jest/console": "^29.4.3", "@jest/reporters": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.4.3", "jest-config": "^29.4.3", "jest-haste-map": "^29.4.3", "jest-message-util": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-resolve-dependencies": "^29.4.3", "jest-runner": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "jest-watcher": "^29.4.3", "micromatch": "^4.0.4", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ=="], "@jest/environment": ["@jest/environment@29.4.3", "", { "dependencies": { "@jest/fake-timers": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "jest-mock": "^29.4.3" } }, "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA=="], @@ -148,7 +148,7 @@ "@jest/globals": ["@jest/globals@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/expect": "^29.4.3", "@jest/types": "^29.4.3", "jest-mock": "^29.4.3" } }, "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA=="], - "@jest/reporters": ["@jest/reporters@29.4.3", "", { "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" } }, "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg=="], + "@jest/reporters": ["@jest/reporters@29.4.3", "", { "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/transform": "^29.4.3", "@jest/types": "^29.4.3", "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.4.3", "jest-util": "^29.4.3", "jest-worker": "^29.4.3", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg=="], "@jest/schemas": ["@jest/schemas@29.4.3", "", { "dependencies": { "@sinclair/typebox": "^0.25.16" } }, "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg=="], @@ -384,13 +384,13 @@ "istanbul-reports": ["istanbul-reports@3.1.5", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w=="], - "jest": ["jest@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/types": "^29.4.3", "import-local": "^3.0.2", "jest-cli": "^29.4.3" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "bin": { "jest": "bin/jest.js" } }, "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA=="], + "jest": ["jest@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/types": "^29.4.3", "import-local": "^3.0.2", "jest-cli": "^29.4.3" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA=="], "jest-changed-files": ["jest-changed-files@29.4.3", "", { "dependencies": { "execa": "^5.0.0", "p-limit": "^3.1.0" } }, "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ=="], "jest-circus": ["jest-circus@29.4.3", "", { "dependencies": { "@jest/environment": "^29.4.3", "@jest/expect": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", "jest-each": "^29.4.3", "jest-matcher-utils": "^29.4.3", "jest-message-util": "^29.4.3", "jest-runtime": "^29.4.3", "jest-snapshot": "^29.4.3", "jest-util": "^29.4.3", "p-limit": "^3.1.0", "pretty-format": "^29.4.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw=="], - "jest-cli": ["jest-cli@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "bin": { "jest": "bin/jest.js" } }, "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg=="], + "jest-cli": ["jest-cli@29.4.3", "", { "dependencies": { "@jest/core": "^29.4.3", "@jest/test-result": "^29.4.3", "@jest/types": "^29.4.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", "jest-config": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg=="], "jest-config": ["jest-config@29.4.3", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.4.3", "@jest/types": "^29.4.3", "babel-jest": "^29.4.3", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-circus": "^29.4.3", "jest-environment-node": "^29.4.3", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", "jest-resolve": "^29.4.3", "jest-runner": "^29.4.3", "jest-util": "^29.4.3", "jest-validate": "^29.4.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", "pretty-format": "^29.4.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "peerDependencies": { "@types/node": "*", "ts-node": ">=9.0.0" }, "optionalPeers": ["ts-node"] }, "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ=="], @@ -600,7 +600,7 @@ "vite": ["vite@4.1.2", "", { "dependencies": { "esbuild": "^0.16.14", "fsevents": "~2.3.2", "postcss": "^8.4.21", "resolve": "^1.22.1", "rollup": "^3.10.0" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["less", "sass", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-MWDb9Rfy3DI8omDQySbMK93nQqStwbsQWejXRY2EBzEWKmLAXWb1mkI9Yw2IJrc+oCvPCI1Os5xSSIBYY6DEAw=="], - "vitest": ["vitest@0.25.8", "", { "dependencies": { "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", "acorn": "^8.8.1", "acorn-walk": "^8.2.0", "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", "source-map": "^0.6.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg=="], + "vitest": ["vitest@0.25.8", "", { "dependencies": { "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", "acorn": "^8.8.1", "acorn-walk": "^8.2.0", "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", "source-map": "^0.6.1", "strip-literal": "^1.0.0", "tinybench": "^2.3.1", "tinypool": "^0.3.0", "tinyspy": "^1.0.2", "vite": "^3.0.0 || ^4.0.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg=="], "walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="], diff --git a/bench/ffi/src/bun.lock b/bench/ffi/src/bun.lock index 8b75ff131f4fe0..c496ad6dba0f74 100644 --- a/bench/ffi/src/bun.lock +++ b/bench/ffi/src/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bench", diff --git a/bench/gzip/bun.lock b/bench/gzip/bun.lock index 2ec377b35795c8..6b706c3f4c3f2b 100644 --- a/bench/gzip/bun.lock +++ b/bench/gzip/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bench", diff --git a/bench/hot-module-reloading/css-stress-test/bun.lock b/bench/hot-module-reloading/css-stress-test/bun.lock index 224235c38d7592..50d59bdb5c93d2 100644 --- a/bench/hot-module-reloading/css-stress-test/bun.lock +++ b/bench/hot-module-reloading/css-stress-test/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "simple-react", @@ -1045,7 +1045,7 @@ "ncp": ["ncp@2.0.0", "", { "bin": { "ncp": "./bin/ncp" } }, "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA=="], - "next": ["next@12.3.4", "", { "dependencies": { "@next/env": "12.3.4", "@next/swc-android-arm-eabi": "12.3.4", "@next/swc-android-arm64": "12.3.4", "@next/swc-darwin-arm64": "12.3.4", "@next/swc-darwin-x64": "12.3.4", "@next/swc-freebsd-x64": "12.3.4", "@next/swc-linux-arm-gnueabihf": "12.3.4", "@next/swc-linux-arm64-gnu": "12.3.4", "@next/swc-linux-arm64-musl": "12.3.4", "@next/swc-linux-x64-gnu": "12.3.4", "@next/swc-linux-x64-musl": "12.3.4", "@next/swc-win32-arm64-msvc": "12.3.4", "@next/swc-win32-ia32-msvc": "12.3.4", "@next/swc-win32-x64-msvc": "12.3.4", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", "styled-jsx": "5.0.7", "use-sync-external-store": "1.2.0" }, "peerDependencies": { "fibers": ">= 3.1.0", "node-sass": "^6.0.0 || ^7.0.0", "react": "^17.0.2 || ^18.0.0-0", "react-dom": "^17.0.2 || ^18.0.0-0", "sass": "^1.3.0" }, "optionalPeers": ["node-sass", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-VcyMJUtLZBGzLKo3oMxrEF0stxh8HwuW976pAzlHhI3t8qJ4SROjCrSh1T24bhrbjw55wfZXAbXPGwPt5FLRfQ=="], + "next": ["next@12.3.4", "", { "dependencies": { "@next/env": "12.3.4", "@next/swc-android-arm-eabi": "12.3.4", "@next/swc-android-arm64": "12.3.4", "@next/swc-darwin-arm64": "12.3.4", "@next/swc-darwin-x64": "12.3.4", "@next/swc-freebsd-x64": "12.3.4", "@next/swc-linux-arm-gnueabihf": "12.3.4", "@next/swc-linux-arm64-gnu": "12.3.4", "@next/swc-linux-arm64-musl": "12.3.4", "@next/swc-linux-x64-gnu": "12.3.4", "@next/swc-linux-x64-musl": "12.3.4", "@next/swc-win32-arm64-msvc": "12.3.4", "@next/swc-win32-ia32-msvc": "12.3.4", "@next/swc-win32-x64-msvc": "12.3.4", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", "styled-jsx": "5.0.7", "use-sync-external-store": "1.2.0" }, "peerDependencies": { "fibers": ">= 3.1.0", "node-sass": "^6.0.0 || ^7.0.0", "react": "^17.0.2 || ^18.0.0-0", "react-dom": "^17.0.2 || ^18.0.0-0", "sass": "^1.3.0" }, "optionalPeers": ["fibers", "node-sass", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-VcyMJUtLZBGzLKo3oMxrEF0stxh8HwuW976pAzlHhI3t8qJ4SROjCrSh1T24bhrbjw55wfZXAbXPGwPt5FLRfQ=="], "nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], @@ -1649,7 +1649,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@7.4.6", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="], + "ws": ["ws@7.4.6", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="], "xml-name-validator": ["xml-name-validator@3.0.0", "", {}, "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="], @@ -1701,7 +1701,7 @@ "@parcel/packager-js/globals": ["globals@13.20.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ=="], - "@parcel/reporter-dev-server/ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="], + "@parcel/reporter-dev-server/ws": ["ws@7.5.9", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="], "@parcel/transformer-babel/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="], diff --git a/bench/react-hello-world/bun.lock b/bench/react-hello-world/bun.lock index 77ae3a343782bb..56594f42eb35f6 100644 --- a/bench/react-hello-world/bun.lock +++ b/bench/react-hello-world/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "react-hello-world", diff --git a/bench/scanner/bun.lock b/bench/scanner/bun.lock index 0640559c71f9e4..60d1e6d8fb7e46 100644 --- a/bench/scanner/bun.lock +++ b/bench/scanner/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "scan", diff --git a/bench/snippets/buffer-create.mjs b/bench/snippets/buffer-create.mjs index ded7f02cab7d60..c9740b7bc20c7b 100644 --- a/bench/snippets/buffer-create.mjs +++ b/bench/snippets/buffer-create.mjs @@ -25,6 +25,10 @@ bench("Buffer.from('short string')", () => { return Buffer.from("short string"); }); +bench("new Buffer('short string')", () => { + return new Buffer("short string"); +}); + const loooong = "long string".repeat(9999).split("").join(" "); bench("Buffer.byteLength('long string'.repeat(9999))", () => { return Buffer.byteLength(loooong); @@ -35,11 +39,19 @@ bench("Buffer.from(ArrayBuffer(100))", () => { return Buffer.from(hundred); }); +bench("new Buffer(ArrayBuffer(100))", () => { + return new Buffer(hundred); +}); + var hundredArray = new Uint8Array(100); bench("Buffer.from(Uint8Array(100))", () => { return Buffer.from(hundredArray); }); +bench("new Buffer(Uint8Array(100))", () => { + return new Buffer(hundredArray); +}); + var empty = new Uint8Array(0); bench("Buffer.from(Uint8Array(0))", () => { return Buffer.from(empty); diff --git a/bench/sqlite/bun.lock b/bench/sqlite/bun.lock index 810e0c4b2e1668..371b6dfb6bc3c6 100644 --- a/bench/sqlite/bun.lock +++ b/bench/sqlite/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bench", diff --git a/bench/websocket-server/bun.lock b/bench/websocket-server/bun.lock index 3587fe51bf8b23..d5e1fc28b3d4b6 100644 --- a/bench/websocket-server/bun.lock +++ b/bench/websocket-server/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "websocket-server", diff --git a/build.zig b/build.zig index abcefc752bd6d5..a487dc66239ee7 100644 --- a/build.zig +++ b/build.zig @@ -19,7 +19,7 @@ const OperatingSystem = @import("src/env.zig").OperatingSystem; const pathRel = fs.path.relative; /// Do not rename this constant. It is scanned by some scripts to determine which zig version to install. -const recommended_zig_version = "0.13.0"; +const recommended_zig_version = "0.14.0-dev.2987+183bb8b08"; comptime { if (!std.mem.eql(u8, builtin.zig_version_string, recommended_zig_version)) { @@ -152,8 +152,7 @@ pub fn getCpuModel(os: OperatingSystem, arch: Arch) ?Target.Query.CpuModel { pub fn build(b: *Build) !void { std.log.info("zig compiler v{s}", .{builtin.zig_version_string}); - - b.zig_lib_dir = b.zig_lib_dir orelse b.path("vendor/zig/lib"); + checked_file_exists = std.AutoHashMap(u64, void).init(b.allocator); // TODO: Upgrade path for 0.14.0 // b.graph.zig_lib_directory = brk: { @@ -208,7 +207,7 @@ pub fn build(b: *Build) !void { const bun_version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0"; b.reference_trace = ref_trace: { - const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 16; + const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 24; break :ref_trace if (trace == 0) null else trace; }; @@ -330,11 +329,25 @@ pub fn build(b: *Build) !void { .{ .os = .windows, .arch = .x86_64 }, }); } + { + const step = b.step("check-macos", "Check for semantic analysis errors on Windows"); + addMultiCheck(b, step, build_options, &.{ + .{ .os = .mac, .arch = .x86_64 }, + .{ .os = .mac, .arch = .aarch64 }, + }); + } + { + const step = b.step("check-linux", "Check for semantic analysis errors on Windows"); + addMultiCheck(b, step, build_options, &.{ + .{ .os = .linux, .arch = .x86_64 }, + .{ .os = .linux, .arch = .aarch64 }, + }); + } // zig build translate-c-headers { const step = b.step("translate-c", "Copy generated translated-c-headers.zig to zig-out"); - step.dependOn(&b.addInstallFile(getTranslateC(b, b.host, .Debug).getOutput(), "translated-c-headers.zig").step); + step.dependOn(&b.addInstallFile(getTranslateC(b, b.graph.host, .Debug).getOutput(), "translated-c-headers.zig").step); } // zig build enum-extractor @@ -362,7 +375,7 @@ pub fn addMultiCheck( const check_target = b.resolveTargetQuery(.{ .os_tag = OperatingSystem.stdOSTag(check.os), .cpu_arch = check.arch, - .cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_cpu_arch, + .cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_arch_os, .os_version_min = getOSVersionMin(check.os), .glibc_version = if (check.musl) null else getOSGlibCVersion(check.os), }); @@ -428,7 +441,6 @@ pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile { .strip = false, // stripped at the end }); obj.bundle_compiler_rt = false; - obj.formatted_panics = true; obj.root_module.omit_frame_pointer = false; // Link libc @@ -481,9 +493,15 @@ pub fn addInstallObjectFile( }, b.fmt("{s}.o", .{name})).step; } +var checked_file_exists: std.AutoHashMap(u64, void) = undefined; fn exists(path: []const u8) bool { - const file = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return false; - file.close(); + const entry = checked_file_exists.getOrPut(std.hash.Wyhash.hash(0, path)) catch unreachable; + if (entry.found_existing) { + // It would've panicked. + return true; + } + + std.fs.accessAbsolute(path, .{ .mode = .read_only }) catch return false; return true; } @@ -607,7 +625,7 @@ const WindowsShim = struct { .optimize = .ReleaseFast, .use_llvm = true, .use_lld = true, - .unwind_tables = false, + .unwind_tables = .none, .omit_frame_pointer = true, .strip = true, .linkage = .static, diff --git a/bun.lock b/bun.lock index b251272571f4a8..4729944dcf9be9 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun", @@ -10,8 +10,8 @@ "@typescript-eslint/eslint-plugin": "^7.11.0", "@typescript-eslint/parser": "^7.11.0", "@vscode/debugadapter": "^1.65.0", - "autoprefixer": "^10.4.19", - "caniuse-lite": "^1.0.30001620", + "autoprefixer": "^10.4.20", + "caniuse-lite": "^1.0.30001660", "esbuild": "^0.21.4", "eslint": "^9.4.0", "eslint-config-prettier": "^9.1.0", @@ -257,7 +257,7 @@ "builtins": ["builtins@1.0.3", "", {}, "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ=="], - "bun-types": ["bun-types@workspace:packages/bun-types", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" }, "devDependencies": { "@biomejs/biome": "^1.5.3", "@definitelytyped/dtslint": "^0.0.199", "@definitelytyped/eslint-plugin": "^0.0.197", "typescript": "^5.0.2" } }], + "bun-types": ["bun-types@workspace:packages/bun-types"], "call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="], @@ -265,7 +265,7 @@ "camel-case": ["camel-case@4.1.2", "", { "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw=="], - "caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + "caniuse-lite": ["caniuse-lite@1.0.30001695", "", {}, "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw=="], "capital-case": ["capital-case@1.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", "upper-case-first": "^2.0.2" } }, "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A=="], @@ -923,10 +923,14 @@ "are-we-there-yet/readable-stream": ["readable-stream@2.3.8", "", { "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-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + "autoprefixer/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + "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" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="], "babel-code-frame/js-tokens": ["js-tokens@3.0.2", "", {}, "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg=="], + "browserslist/caniuse-lite": ["caniuse-lite@1.0.30001653", "", {}, "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw=="], + "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], diff --git a/cmake/scripts/DownloadZig.cmake b/cmake/scripts/DownloadZig.cmake index f7f9d8789e90d6..590a443f444009 100644 --- a/cmake/scripts/DownloadZig.cmake +++ b/cmake/scripts/DownloadZig.cmake @@ -38,7 +38,7 @@ else() set(ZIG_FILENAME ${ZIG_NAME}.tar.xz) endif() -set(ZIG_DOWNLOAD_URL https://ziglang.org/download/${ZIG_VERSION}/${ZIG_FILENAME}) +set(ZIG_DOWNLOAD_URL https://bun-ci-assets.bun.sh/${ZIG_FILENAME}) execute_process( COMMAND diff --git a/cmake/targets/BuildBun.cmake b/cmake/targets/BuildBun.cmake index ad1ce07f33ddc6..1066e31a5d0500 100644 --- a/cmake/targets/BuildBun.cmake +++ b/cmake/targets/BuildBun.cmake @@ -404,6 +404,7 @@ set(BUN_OBJECT_LUT_SOURCES ${CWD}/src/bun.js/bindings/ZigGlobalObject.lut.txt ${CWD}/src/bun.js/bindings/JSBuffer.cpp ${CWD}/src/bun.js/bindings/BunProcess.cpp + ${CWD}/src/bun.js/bindings/ProcessBindingBuffer.cpp ${CWD}/src/bun.js/bindings/ProcessBindingConstants.cpp ${CWD}/src/bun.js/bindings/ProcessBindingNatives.cpp ${CWD}/src/bun.js/modules/NodeModuleModule.cpp @@ -415,6 +416,7 @@ set(BUN_OBJECT_LUT_OUTPUTS ${CODEGEN_PATH}/ZigGlobalObject.lut.h ${CODEGEN_PATH}/JSBuffer.lut.h ${CODEGEN_PATH}/BunProcess.lut.h + ${CODEGEN_PATH}/ProcessBindingBuffer.lut.h ${CODEGEN_PATH}/ProcessBindingConstants.lut.h ${CODEGEN_PATH}/ProcessBindingNatives.lut.h ${CODEGEN_PATH}/NodeModuleModule.lut.h diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index d00d3a3e96eecb..6c3f8a9619c8ab 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 9e3b60e4a6438d20ee6f8aa5bec6b71d2b7d213f) + set(WEBKIT_VERSION e32c6356625cfacebff0c61d182f759abf6f508a) endif() string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX) diff --git a/cmake/tools/SetupZig.cmake b/cmake/tools/SetupZig.cmake index e5a5e574ef99aa..00cab1c61bffd7 100644 --- a/cmake/tools/SetupZig.cmake +++ b/cmake/tools/SetupZig.cmake @@ -20,8 +20,8 @@ else() unsupported(CMAKE_SYSTEM_NAME) endif() -optionx(ZIG_VERSION STRING "The zig version of the compiler to download" DEFAULT "0.13.0") -optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "131a009ba2eb127a3447d05b9e12f710429aa5ee") +optionx(ZIG_VERSION STRING "The zig version of the compiler to download" DEFAULT "0.14.0-dev.2987+183bb8b08") +optionx(ZIG_COMMIT STRING "The zig commit to use in oven-sh/zig" DEFAULT "568a19ea4b811a5580bbf869cdaf6071244b9bb2") optionx(ZIG_TARGET STRING "The zig target to use" DEFAULT ${DEFAULT_ZIG_TARGET}) if(CMAKE_BUILD_TYPE STREQUAL "Release") diff --git a/dockerhub/distroless/Dockerfile b/dockerhub/distroless/Dockerfile index fb8e985d0b1cf8..a27540ddcb6df4 100644 --- a/dockerhub/distroless/Dockerfile +++ b/dockerhub/distroless/Dockerfile @@ -67,14 +67,18 @@ ARG BUN_INSTALL_BIN=/usr/local/bin ENV BUN_INSTALL_BIN=${BUN_INSTALL_BIN} COPY --from=build /usr/local/bin/bun /usr/local/bin/ -RUN mkdir -p /usr/local/bun-node-fallback-bin && ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node ENV PATH "${PATH}:/usr/local/bun-node-fallback-bin" # Temporarily use the `build`-stage image binaries to create a symlink: RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \ - --mount=type=bind,from=build,source=/bin,target=/bin < + +### server.timeout(Request, seconds) - Custom request timeouts + +Set a custom idle timeout for individual requests: + +```ts +const server = Bun.serve({ + fetch(req, server) { + // Set 60 second timeout for this request + server.timeout(req, 60); + + // If they take longer than 60 seconds to send the body, the request will be aborted + await req.text(); + + return new Response("Done!"); + }, +}); +``` + +Pass `0` to disable the timeout for a request. + +### server.requestIP(Request) - Get client information + +Get client IP and port information: + +```ts +const server = Bun.serve({ + fetch(req, server) { + const address = server.requestIP(req); + if (address) { + return new Response( + `Client IP: ${address.address}, Port: ${address.port}`, + ); + } + return new Response("Unknown client"); + }, +}); +``` + +Returns `null` for closed requests or Unix domain sockets. + +## Server Metrics + +### server.pendingRequests and server.pendingWebSockets + +Monitor server activity with built-in counters: + +```ts +const server = Bun.serve({ + fetch(req, server) { + return new Response( + `Active requests: ${server.pendingRequests}\n` + + `Active WebSockets: ${server.pendingWebSockets}`, + ); + }, +}); +``` + +### server.subscriberCount(topic) - WebSocket subscribers + +Get count of subscribers for a WebSocket topic: + +```ts +const server = Bun.serve({ + fetch(req, server) { + const chatUsers = server.subscriberCount("chat"); + return new Response(`${chatUsers} users in chat`); + }, + websocket: { + message(ws) { + ws.subscribe("chat"); + }, + }, +}); +``` + +## WebSocket Configuration + +### server.publish(topic, data, compress) - WebSocket Message Publishing + +The server can publish messages to all WebSocket clients subscribed to a topic: + +```ts +const server = Bun.serve({ + websocket: { + message(ws) { + // Publish to all "chat" subscribers + server.publish("chat", "Hello everyone!"); + }, + }, + + fetch(req) { + // ... + }, +}); +``` + +The `publish()` method returns: + +- Number of bytes sent if successful +- `0` if the message was dropped +- `-1` if backpressure was applied + +### WebSocket Handler Options + +When configuring WebSockets, several advanced options are available through the `websocket` handler: + +```ts +Bun.serve({ + websocket: { + // Maximum message size (in bytes) + maxPayloadLength: 64 * 1024, + + // Backpressure limit before messages are dropped + backpressureLimit: 1024 * 1024, + + // Close connection if backpressure limit is hit + closeOnBackpressureLimit: true, + + // Handler called when backpressure is relieved + drain(ws) { + console.log("Backpressure relieved"); + }, + + // Enable per-message deflate compression + perMessageDeflate: { + compress: true, + decompress: true, + }, + + // Send ping frames to keep connection alive + sendPings: true, + + // Handlers for ping/pong frames + ping(ws, data) { + console.log("Received ping"); + }, + pong(ws, data) { + console.log("Received pong"); + }, + + // Whether server receives its own published messages + publishToSelf: false, + }, +}); +``` + ## Benchmarks Below are Bun and Node.js implementations of a simple HTTP server that responds `Bun!` to each incoming `Request`. @@ -561,100 +796,174 @@ The `Bun.serve` server can handle roughly 2.5x more requests per second than Nod {% details summary="See TypeScript definitions" %} ```ts -interface Bun { - serve(options: { - development?: boolean; - error?: ( - request: ErrorLike, - ) => Response | Promise | undefined | Promise; - fetch(request: Request, server: Server): Response | Promise; - hostname?: string; - id?: string | null; - maxRequestBodySize?: number; - port?: string | number; - reusePort?: boolean; - tls?: TLSOptions | Array; - unix: string; - websocket: WebSocketHandler; - }): Server; -} +interface Server extends Disposable { + /** + * Stop the server from accepting new connections. + * @param closeActiveConnections If true, immediately terminates all connections + * @returns Promise that resolves when the server has stopped + */ + stop(closeActiveConnections?: boolean): Promise; + + /** + * Update handlers without restarting the server. + * Only fetch and error handlers can be updated. + */ + reload(options: Serve): void; -interface TLSOptions { - ca?: string | Buffer | BunFile | Array | undefined; - cert?: - | string - | Buffer - | BunFile - | Array - | undefined; - dhParamsFile?: string; - key?: - | string - | Buffer - | BunFile - | Array - | undefined; - lowMemoryMode?: boolean; - passphrase?: string; - secureOptions?: number | undefined; - serverName?: string; + /** + * Make a request to the running server. + * Useful for testing or internal routing. + */ + fetch(request: Request | string): Response | Promise; + + /** + * Upgrade an HTTP request to a WebSocket connection. + * @returns true if upgrade successful, false if failed + */ + upgrade( + request: Request, + options?: { + headers?: Bun.HeadersInit; + data?: T; + }, + ): boolean; + + /** + * Publish a message to all WebSocket clients subscribed to a topic. + * @returns Bytes sent, 0 if dropped, -1 if backpressure applied + */ + publish( + topic: string, + data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + compress?: boolean, + ): ServerWebSocketSendStatus; + + /** + * Get count of WebSocket clients subscribed to a topic. + */ + subscriberCount(topic: string): number; + + /** + * Get client IP address and port. + * @returns null for closed requests or Unix sockets + */ + requestIP(request: Request): SocketAddress | null; + + /** + * Set custom idle timeout for a request. + * @param seconds Timeout in seconds, 0 to disable + */ + timeout(request: Request, seconds: number): void; + + /** + * Keep process alive while server is running. + */ + ref(): void; + + /** + * Allow process to exit if server is only thing running. + */ + unref(): void; + + /** Number of in-flight HTTP requests */ + readonly pendingRequests: number; + + /** Number of active WebSocket connections */ + readonly pendingWebSockets: number; + + /** Server URL including protocol, hostname and port */ + readonly url: URL; + + /** Port server is listening on */ + readonly port: number; + + /** Hostname server is bound to */ + readonly hostname: string; + + /** Whether server is in development mode */ + readonly development: boolean; + + /** Server instance identifier */ + readonly id: string; } interface WebSocketHandler { + /** Maximum WebSocket message size in bytes */ + maxPayloadLength?: number; + + /** Bytes of queued messages before applying backpressure */ backpressureLimit?: number; - close?( - ws: ServerWebSocket, - code: number, - reason: string, - ): void | Promise; + + /** Whether to close connection when backpressure limit hit */ closeOnBackpressureLimit?: boolean; + + /** Called when backpressure is relieved */ drain?(ws: ServerWebSocket): void | Promise; + + /** Seconds before idle timeout */ idleTimeout?: number; - maxPayloadLength?: number; - message( - ws: ServerWebSocket, - message: string | Buffer, - ): void | Promise; - open?(ws: ServerWebSocket): void | Promise; + + /** Enable per-message deflate compression */ perMessageDeflate?: | boolean | { compress?: WebSocketCompressor | boolean; decompress?: WebSocketCompressor | boolean; }; + + /** Send ping frames to keep connection alive */ + sendPings?: boolean; + + /** Whether server receives its own published messages */ + publishToSelf?: boolean; + + /** Called when connection opened */ + open?(ws: ServerWebSocket): void | Promise; + + /** Called when message received */ + message( + ws: ServerWebSocket, + message: string | Buffer, + ): void | Promise; + + /** Called when connection closed */ + close?( + ws: ServerWebSocket, + code: number, + reason: string, + ): void | Promise; + + /** Called when ping frame received */ ping?(ws: ServerWebSocket, data: Buffer): void | Promise; + + /** Called when pong frame received */ pong?(ws: ServerWebSocket, data: Buffer): void | Promise; - publishToSelf?: boolean; - sendPings?: boolean; } -interface Server { - fetch(request: Request | string): Response | Promise; - publish( - compress?: boolean, - data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, - topic: string, - ): ServerWebSocketSendStatus; - ref(): void; - reload(options: Serve): void; - requestIP(request: Request): SocketAddress | null; - stop(closeActiveConnections?: boolean): void; - unref(): void; - upgrade( - options?: { - data?: T; - headers?: Bun.HeadersInit; - }, - request: Request, - ): boolean; +interface TLSOptions { + /** Certificate authority chain */ + ca?: string | Buffer | BunFile | Array; - readonly development: boolean; - readonly hostname: string; - readonly id: string; - readonly pendingRequests: number; - readonly pendingWebSockets: number; - readonly port: number; - readonly url: URL; + /** Server certificate */ + cert?: string | Buffer | BunFile | Array; + + /** Path to DH parameters file */ + dhParamsFile?: string; + + /** Private key */ + key?: string | Buffer | BunFile | Array; + + /** Reduce TLS memory usage */ + lowMemoryMode?: boolean; + + /** Private key passphrase */ + passphrase?: string; + + /** OpenSSL options flags */ + secureOptions?: number; + + /** Server name for SNI */ + serverName?: string; } ``` diff --git a/docs/bundler/fullstack.md b/docs/bundler/fullstack.md index 0d6909bb69ab63..0496899cf09cb5 100644 --- a/docs/bundler/fullstack.md +++ b/docs/bundler/fullstack.md @@ -1,12 +1,12 @@ -As of Bun v1.1.44, we've added initial support for bundling frontend apps directly in Bun's HTTP server: `Bun.serve()`. Run your frontend and backend in the same app with no extra steps. +Using `Bun.serve()`'s `static` option, you can run your frontend and backend in the same app with no extra steps. -To get started, import your HTML files and pass them to the `static` option in `Bun.serve()`. +To get started, import HTML files and pass them to the `static` option in `Bun.serve()`. ```ts import dashboard from "./dashboard.html"; import homepage from "./index.html"; -Bun.serve({ +const server = Bun.serve({ // Add HTML imports to `static` static: { // Bundle & route index.html to "/" @@ -32,6 +32,8 @@ Bun.serve({ return new Response("Not Found", { status: 404 }); }, }); + +console.log(`Listening on ${server.url}`); ``` ```bash @@ -107,7 +109,7 @@ To use React in your client-side code, import `react-dom/client` and render your {% codetabs %} ```ts#src/backend.ts -import dashboard from "./public/dashboard.html"; +import dashboard from "../public/dashboard.html"; import { serve } from "bun"; serve({ @@ -204,18 +206,20 @@ To configure plugins for `Bun.serve`, add a `plugins` array in the `[serve.stati ### Using TailwindCSS in HTML routes -For example, enable TailwindCSS on your routes by adding add the `bun-plugin-tailwind` plugin: +For example, enable TailwindCSS on your routes by installing and adding the `bun-plugin-tailwind` plugin: + +```sh +$ bun add bun-plugin-tailwind +``` -```toml +```toml#bunfig.toml [serve.static] plugins = ["bun-plugin-tailwind"] - ``` This will allow you to use TailwindCSS utility classes in your HTML and CSS files. All you need to do is import `tailwindcss` somewhere: -```html - +```html#index.html @@ -230,14 +234,15 @@ This will allow you to use TailwindCSS utility classes in your HTML and CSS file Or in your CSS: -```css -/* style.css */ +```css#style.css @import "tailwindcss"; ``` +### Custom plugins + Any JS file or module which exports a [valid bundler plugin object](https://bun.sh/docs/bundler/plugins#usage) (essentially an object with a `name` and `setup` field) can be placed inside the `plugins` array: -```toml +```toml#bunfig.toml [serve.static] plugins = ["./my-plugin-implementation.ts"] ``` diff --git a/docs/bundler/html.md b/docs/bundler/html.md index e295a7962873ae..0edee9835f3358 100644 --- a/docs/bundler/html.md +++ b/docs/bundler/html.md @@ -1,4 +1,4 @@ -As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else. +Bun's bundler has first-class support for HTML. Build static sites, landing pages, and web applications with zero configuration. Just point Bun at your HTML file and it handles everything else. ```html#index.html @@ -13,45 +13,228 @@ As of Bun v1.1.43, Bun's bundler now has first-class support for HTML. Build sta ``` -One command is all you need (won't be experimental after Bun v1.2): +To get started, pass HTML files to `bun`. + +{% bunDevServerTerminal alt="bun ./index.html" path="./index.html" routes="" /%} + +Bun's development server provides powerful features with zero configuration: + +- **Automatic Bundling** - Bundles and serves your HTML, JavaScript, and CSS +- **Multi-Entry Support** - Handles multiple HTML entry points and glob entry points +- **Modern JavaScript** - TypeScript & JSX support out of the box +- **Smart Configuration** - Reads `tsconfig.json` for paths, JSX options, experimental decorators, and more +- **Plugins** - Plugins for TailwindCSS and more +- **ESM & CommonJS** - Use ESM and CommonJS in your JavaScript, TypeScript, and JSX files +- **CSS Bundling & Minification** - Bundles CSS from `` tags and `@import` statements +- **Asset Management** + - Automatic copying & hashing of images and assets + - Rewrites asset paths in JavaScript, CSS, and HTML + +## Single Page Apps (SPA) + +When you pass a single .html file to Bun, Bun will use it as a fallback route for all paths. This makes it perfect for single page apps that use client-side routing: + +{% bunDevServerTerminal alt="bun index.html" path="index.html" routes="" /%} + +Your React or other SPA will work out of the box — no configuration needed. All routes like `/about`, `/users/123`, etc. will serve the same HTML file, letting your client-side router handle the navigation. + +```html#index.html + + + + My SPA + + + +
+ + +``` + +## Multi-page apps (MPA) + +Some projects have several separate routes or HTML files as entry points. To support multiple entry points, pass them all to `bun` + +{% bunDevServerTerminal alt="bun ./index.html ./about.html" path="./index.html ./about.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about.html\"}]" /%} + +This will serve: + +- `index.html` at `/` +- `about.html` at `/about` + +### Glob patterns + +To specify multiple files, you can use glob patterns that end in `.html`: + +{% bunDevServerTerminal alt="bun ./**/*.html" path="./**/*.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about.html\"}]" /%} + +### Path normalization + +The base path is chosen from the longest common prefix among all the files. + +{% bunDevServerTerminal alt="bun ./index.html ./about/index.html ./about/foo/index.html" path="./index.html ./about/index.html ./about/foo/index.html" routes="[{\"path\": \"/\", \"file\": \"./index.html\"}, {\"path\": \"/about\", \"file\": \"./about/index.html\"}, {\"path\": \"/about/foo\", \"file\": \"./about/foo/index.html\"}]" /%} + +## JavaScript, TypeScript, and JSX + +Bun's transpiler natively implements JavaScript, TypeScript, and JSX support. [Learn more about loaders in Bun](/docs/bundler/loaders). + +Bun's transpiler is also used at runtime. + +### ES Modules & CommonJS + +You can use ESM and CJS in your JavaScript, TypeScript, and JSX files. Bun will handle the transpilation and bundling automatically. + +There is no pre-build or separate optimization step. It's all done at the same time. + +Learn more about [module resolution in Bun](/docs/runtime/modules). + +## CSS + +Bun's CSS parser is also natively implemented (clocking in around 58,000 lines of Zig). + +It's also a CSS bundler. You can use `@import` in your CSS files to import other CSS files. + +For example: + +```css#styles.css +@import "./abc.css"; + +.container { + background-color: blue; +} +``` + +```css#abc.css +body { + background-color: red; +} +``` + +This outputs: + +```css#styles.css +body { + background-color: red; +} + +.container { + background-color: blue; +} +``` + +### Referencing local assets in CSS + +You can reference local assets in your CSS files. + +```css#styles.css +body { + background-image: url("./logo.png"); +} +``` + +This will copy `./logo.png` to the output directory and rewrite the path in the CSS file to include a content hash. + +```css#styles.css +body { + background-image: url("./logo-[ABC123].png"); +} +``` + +### Importing CSS in JavaScript + +To associate a CSS file with a JavaScript file, you can import it in your JavaScript file. + +```ts#app.ts +import "./styles.css"; +import "./more-styles.css"; +``` + +This generates `./app.css` and `./app.js` in the output directory. All CSS files imported from JavaScript will be bundled into a single CSS file per entry point. If you import the same CSS file from multiple JavaScript files, it will only be included once in the output CSS file. + +## Plugins + +The dev server supports plugins. + +### Tailwind CSS + +To use TailwindCSS, install the `bun-plugin-tailwind` plugin: + +```bash +# Or any npm client +$ bun install --dev bun-plugin-tailwind +``` + +Then, add the plugin to your `bunfig.toml`: + +```toml +[serve.static] +plugins = ["bun-plugin-tailwind"] +``` + +Then, reference TailwindCSS in your HTML via `` tag, `@import` in CSS, or `import` in JavaScript. + +{% codetabs %} + +```html#index.html + + +``` + +```css#styles.css +/* Import TailwindCSS in your CSS */ +@import "tailwindcss"; +``` + +```ts#app.ts +/* Import TailwindCSS in your JavaScript */ +import "tailwindcss"; +``` + +{% /codetabs %} + +Only one of those are necessary, not all three. + +## Keyboard Shortcuts + +While the server is running: + +- `o + Enter` - Open in browser +- `c + Enter` - Clear console +- `q + Enter` (or Ctrl+C) - Quit server + +## Build for Production + +When you're ready to deploy, use `bun build` to create optimized production bundles: {% codetabs %} ```bash#CLI -$ bun build ./index.html --outdir=dist +$ bun build ./index.html --minify --outdir=dist ``` ```ts#API Bun.build({ entrypoints: ["./index.html"], outdir: "./dist", + minify: { + whitespace: true, + identifiers: true, + syntax: true, + } }); ``` {% /codetabs %} -Bun automatically: +Currently, plugins are only supported through `Bun.build`'s API or through `bunfig.toml` with the frontend dev server - not yet supported in `bun build`'s CLI. -- Bundles, tree-shakes, and optimizes your JavaScript, JSX and TypeScript -- Bundles and optimizes your CSS -- Copies & hashes images and other assets -- Updates all references to local files or packages in your HTML +### Watch Mode -## Zero Config, Maximum Performance - -The HTML bundler is enabled by default after Bun v1.2+. Drop in your existing HTML files and Bun will handle: - -- **TypeScript & JSX** - Write modern JavaScript for browsers without the setup -- **CSS** - Bundle CSS stylesheets directly from `` or `@import` -- **Images & Assets** - Automatic copying & hashing & rewriting of assets in JavaScript, CSS, and HTML - -## Watch mode - -You can run `bun build --watch` to watch for changes and rebuild automatically. +You can run `bun build --watch` to watch for changes and rebuild automatically. This works nicely for library development. You've never seen a watch mode this fast. -## Plugin API +### Plugin API Need more control? Configure the bundler through the JavaScript API and use Bun's builtin `HTMLRewriter` to preprocess HTML. @@ -102,3 +285,22 @@ Bun automatically handles all common web assets: - Any `` tag with an `href` attribute pointing to a local file is rewritten to the new path, and hashed All paths are resolved relative to your HTML file, making it easy to organize your project however you want. + +## This is a work in progress + +- No HMR support yet +- Need more plugins +- Need more configuration options for things like asset handling +- Need a way to configure CORS, headers, etc. + +If you want to submit a PR, most of the [code is here](https://github.com/oven-sh/bun/blob/main/src/js/internal/html.ts). You could even copy paste that file into your project and use it as a starting point. + +## How this works + +This is a small wrapper around Bun's support for HTML imports in JavaScript. + +### Adding a backend to your frontend + +To add a backend to your frontend, you can use the `"static"` option in `Bun.serve`. + +Learn more in [the full-stack docs](/docs/bundler/fullstack). diff --git a/docs/guides/ecosystem/drizzle.md b/docs/guides/ecosystem/drizzle.md index 9b8c239b7168f4..ef2f102580899a 100644 --- a/docs/guides/ecosystem/drizzle.md +++ b/docs/guides/ecosystem/drizzle.md @@ -98,7 +98,7 @@ import { Database } from "bun:sqlite"; const sqlite = new Database("sqlite.db"); const db = drizzle(sqlite); -await migrate(db, { migrationsFolder: "./drizzle" }); +migrate(db, { migrationsFolder: "./drizzle" }); ``` --- diff --git a/docs/guides/runtime/cicd.md b/docs/guides/runtime/cicd.md index b94d22140a82bb..c536a4dc0d2d2a 100644 --- a/docs/guides/runtime/cicd.md +++ b/docs/guides/runtime/cicd.md @@ -35,7 +35,7 @@ jobs: # ... - uses: oven-sh/setup-bun@v2 + with: -+ bun-version: 1.0.11 # or "latest", "canary", ++ bun-version: 1.2.0 # or "latest", "canary", ``` --- diff --git a/docs/nav.ts b/docs/nav.ts index 615c1ce7df4af7..ff4f803e34e9f6 100644 --- a/docs/nav.ts +++ b/docs/nav.ts @@ -214,7 +214,7 @@ export default { page("bundler", "`Bun.build`", { description: "Bundle code for consumption in the browser with Bun's native bundler.", }), - page("bundler/html", "HTML", { + page("bundler/html", "Frontend & static sites", { description: `Bundle html files with Bun's native bundler.`, }), page("bundler/fullstack", "Fullstack Dev Server", { diff --git a/docs/runtime/bunfig.md b/docs/runtime/bunfig.md index 36dfa750439307..01c2843f361ee1 100644 --- a/docs/runtime/bunfig.md +++ b/docs/runtime/bunfig.md @@ -180,6 +180,25 @@ Whether to skip test files when computing coverage statistics. Default `false`. coverageSkipTestFiles = false ``` +### `test.coverageReporter` + +By default, coverage reports will be printed to the console. For persistent code coverage reports in CI environments and for other tools use `lcov`. + +```toml +[test] +coverageReporter = ["text", "lcov"] # default ["text"] +``` + +### `test.coverageDir` + +Set path where coverage reports will be saved. Please notice, that it works only for persistent `coverageReporter` like `lcov`. + +```toml +[test] +coverageDir = "path/to/somewhere" # default "coverage" +``` + + ## Package manager Package management is a complex issue; to support a range of use cases, the behavior of `bun install` can be configured under the `[install]` section. diff --git a/docs/runtime/typescript.md b/docs/runtime/typescript.md index 752dc2b9b93661..d7b5f7726ef32b 100644 --- a/docs/runtime/typescript.md +++ b/docs/runtime/typescript.md @@ -58,3 +58,82 @@ export const foo = "Hello world!" ``` {% /codetabs %} + +## Experimental Decorators + +Bun supports the pre-TypeScript 5.0 experimental decorators syntax. + +```ts#hello.ts +// Simple logging decorator +function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) { + const originalMethod = descriptor.value; + + descriptor.value = function(...args: any[]) { + console.log(`Calling ${propertyKey} with:`, args); + return originalMethod.apply(this, args); + }; +} + +class Example { + @log + greet(name: string) { + return `Hello ${name}!`; + } +} + +// Usage +const example = new Example(); +example.greet("world"); // Logs: "Calling greet with: ['world']" +``` + +To enable it, add `"experimentalDecorators": true` to your `tsconfig.json`: + +```jsonc#tsconfig.json +{ + "compilerOptions": { + // ... rest of your config + "experimentalDecorators": true, + }, +} +``` + +We generally don't recommend using this in new codebases, but plenty of existing codebases have come to rely on it. + +### emitDecoratorMetadata + +Bun supports `emitDecoratorMetadata` in your `tsconfig.json`. This enables emitting design-time type metadata for decorated declarations in source files. + +```ts#emit-decorator-metadata.ts +import "reflect-metadata"; + +class User { + id: number; + name: string; +} + +function Injectable(target: Function) { + // Get metadata about constructor parameters + const params = Reflect.getMetadata("design:paramtypes", target); + console.log("Dependencies:", params); // [User] +} + +@Injectable +class UserService { + constructor(private user: User) {} +} + +// Creates new UserService instance with dependencies +const container = new UserService(new User()); +``` + +To enable it, add `"emitDecoratorMetadata": true` to your `tsconfig.json`: + +```jsonc#tsconfig.json +{ + "compilerOptions": { + // ... rest of your config + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + }, +} +``` diff --git a/examples/macros/bun.lock b/examples/macros/bun.lock index 2be2580af77a50..9098490d137c5c 100644 --- a/examples/macros/bun.lock +++ b/examples/macros/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "macros", diff --git a/examples/react-fast-refresh-test/bun.lock b/examples/react-fast-refresh-test/bun.lock index c561151911282a..beb92f067776b2 100644 --- a/examples/react-fast-refresh-test/bun.lock +++ b/examples/react-fast-refresh-test/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "simple-react", @@ -1049,7 +1049,7 @@ "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": ["node-sass", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-GWQJrWYkfAKP8vmrzJcCfRSKv955Khyjqd5jipTcVKDGg+SH+NfjDMWFtCwArcQlHPvzisGu1ERLY0+Eoj7G+g=="], + "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=="], @@ -1659,7 +1659,7 @@ "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": ["utf-8-validate"] }, "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="], + "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=="], diff --git a/oxlint.json b/oxlint.json index f596253eb7ed58..c5f1279d7358ad 100644 --- a/oxlint.json +++ b/oxlint.json @@ -20,6 +20,7 @@ "build", "test/snapshots/**", "bench/react-hello-world/*.js", + "bun.lock", "test/js/node/**/parallel/**", "test/js/node/test/fixtures", // full of JS with intentional syntax errors diff --git a/package.json b/package.json index 268ffd2c3f44a5..45c9ed7b50a362 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "bun", - "version": "1.2.0", + "version": "1.2.3", "workspaces": [ "./packages/bun-types" ], @@ -22,8 +22,8 @@ "react-dom": "^18.3.1", "source-map-js": "^1.2.0", "typescript": "^5.7.2", - "caniuse-lite": "^1.0.30001620", - "autoprefixer": "^10.4.19", + "caniuse-lite": "^1.0.30001660", + "autoprefixer": "^10.4.20", "@mdn/browser-compat-data": "~5.5.28" }, "resolutions": { diff --git a/packages/bun-debug-adapter-protocol/bun.lock b/packages/bun-debug-adapter-protocol/bun.lock index c6f5669fbee602..67640d46304d79 100644 --- a/packages/bun-debug-adapter-protocol/bun.lock +++ b/packages/bun-debug-adapter-protocol/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun-debug-adapter-protocol", diff --git a/packages/bun-inspector-frontend/bun.lock b/packages/bun-inspector-frontend/bun.lock index 69c4f0f953d7d0..df761e69be3c84 100644 --- a/packages/bun-inspector-frontend/bun.lock +++ b/packages/bun-inspector-frontend/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "web-inspector-bun", @@ -12,6 +12,9 @@ "peerDependencies": { "typescript": "^5.0.0", }, + "optionalPeers": [ + "typescript", + ], }, }, "packages": { diff --git a/packages/bun-inspector-protocol/bun.lock b/packages/bun-inspector-protocol/bun.lock index e2f91c874ccc8f..4d58b46a113df0 100644 --- a/packages/bun-inspector-protocol/bun.lock +++ b/packages/bun-inspector-protocol/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun-inspector-protocol", @@ -9,6 +9,6 @@ }, }, "packages": { - "ws": ["ws@8.13.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA=="], + "ws": ["ws@8.13.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA=="], } } diff --git a/packages/bun-internal-test/bun.lock b/packages/bun-internal-test/bun.lock index 92bab9001b5d9c..ce702ec37ae94b 100644 --- a/packages/bun-internal-test/bun.lock +++ b/packages/bun-internal-test/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { @@ -26,7 +26,7 @@ "@types/p-queue": ["@types/p-queue@3.2.1", "", { "dependencies": { "p-queue": "*" } }, "sha512-tgAdn5zEs05NuHzOyRM34cMO0rczStphR/kLo/ZJwwwJ5S2+QVxwA6gST3vDHWPB1oDfUuT6wOouhJvJkBCA0w=="], - "bun": ["bun@workspace:runners/bun", {}], + "bun": ["bun@workspace:runners/bun"], "bun-types": ["bun-types@1.0.4-canary.20230929T233451", "", {}, "sha512-Ke/y3GX0T2ZYKx0UKKCnFRRP9bXzVRcRZCrIlF5/aRNEpgbfrMBw+s5imPqrV2CqJ7q6kIbMikCahzMr4N9PTg=="], @@ -38,7 +38,7 @@ "prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], - "qunit": ["qunit@workspace:runners/qunit", {}], + "qunit": ["qunit@workspace:runners/qunit"], "tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="], diff --git a/packages/bun-lambda/bun.lock b/packages/bun-lambda/bun.lock index 83bb7e5474defb..203e5a87412b1e 100644 --- a/packages/bun-lambda/bun.lock +++ b/packages/bun-lambda/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { diff --git a/packages/bun-lambda/runtime.ts b/packages/bun-lambda/runtime.ts index f5de8a7e1c901d..791624b52b880e 100755 --- a/packages/bun-lambda/runtime.ts +++ b/packages/bun-lambda/runtime.ts @@ -364,17 +364,15 @@ function formatHttpEventV2(event: HttpEventV2): Request { headers.append(name, value); } } - for (const [name, values] of Object.entries(event.queryStringParameters ?? {})) { - for (const value of values.split(",")) { - headers.append(name, value); - } - } for (const cookie of event.cookies ?? []) { headers.append("Set-Cookie", cookie); } const hostname = headers.get("Host") ?? request.domainName; const proto = headers.get("X-Forwarded-Proto") ?? "http"; const url = new URL(request.http.path, `${proto}://${hostname}/`); + for (const [name, values] of Object.entries(event.queryStringParameters ?? {})) { + url.searchParams.append(name, values); + } return new Request(url.toString(), { method: request.http.method, headers, diff --git a/packages/bun-native-plugin-rs/Cargo.toml b/packages/bun-native-plugin-rs/Cargo.toml index 8ab8e3fa7fb9b8..b6ebc1206391f9 100644 --- a/packages/bun-native-plugin-rs/Cargo.toml +++ b/packages/bun-native-plugin-rs/Cargo.toml @@ -2,16 +2,12 @@ name = "bun-native-plugin" description = "Rustified wrapper for writing native plugins for Bun." license = "MIT" -version = "0.1.2" +version = "0.2.0" edition = "2021" [dependencies] anyhow = "1.0.94" # use local path in dev and publish to crates.io in prod bun-macro = { path = "./bun-macro", version = "0.1.0" } -napi = { version = "2.14.1", default-features = false, features = ["napi4"] } -[features] -default = ["napi"] -napi = [] diff --git a/packages/bun-native-plugin-rs/src/lib.rs b/packages/bun-native-plugin-rs/src/lib.rs index e477bc5645b7a9..b732578a4c063b 100644 --- a/packages/bun-native-plugin-rs/src/lib.rs +++ b/packages/bun-native-plugin-rs/src/lib.rs @@ -473,6 +473,10 @@ impl<'a> OnBeforeParse<'a> { } } + /// # Safety + /// This is unsafe as you must ensure that no other invocation of the plugin (or JS!) + /// simultaneously holds a mutable reference to the external. + /// /// Get the external object from the `OnBeforeParse` arguments. /// /// The external object is set by the plugin definition inside of JS: @@ -521,42 +525,35 @@ impl<'a> OnBeforeParse<'a> { /// }, /// }; /// ``` - pub unsafe fn external(&self) -> PluginResult> { + pub unsafe fn external<'b, T: 'static + Sync>( + &self, + from_raw: unsafe fn(*mut c_void) -> Option<&'b T>, + ) -> PluginResult> { if unsafe { (*self.args_raw).external.is_null() } { return Ok(None); } - let external: *mut TaggedObject = - unsafe { (*self.args_raw).external as *mut TaggedObject }; - - unsafe { - if (*external).type_id != TypeId::of::() { - return Err(Error::ExternalTypeMismatch); - } + let external = unsafe { from_raw((*self.args_raw).external as *mut _) }; - Ok((*external).object.as_ref()) - } + Ok(external) } /// The same as [`crate::bun_native_plugin::OnBeforeParse::external`], but returns a mutable reference. /// - /// This is unsafe as you must ensure that no other invocation of the plugin + /// # Safety + /// This is unsafe as you must ensure that no other invocation of the plugin (or JS!) /// simultaneously holds a mutable reference to the external. - pub unsafe fn external_mut(&mut self) -> PluginResult> { + pub unsafe fn external_mut<'b, T: 'static + Sync>( + &mut self, + from_raw: unsafe fn(*mut c_void) -> Option<&'b mut T>, + ) -> PluginResult> { if unsafe { (*self.args_raw).external.is_null() } { return Ok(None); } - let external: *mut TaggedObject = - unsafe { (*self.args_raw).external as *mut TaggedObject }; + let external = unsafe { from_raw((*self.args_raw).external as *mut _) }; - unsafe { - if (*external).type_id != TypeId::of::() { - return Err(Error::ExternalTypeMismatch); - } - - Ok((*external).object.as_mut()) - } + Ok(external) } /// Get the input source code for the current file. diff --git a/packages/bun-plugin-yaml/bun.lock b/packages/bun-plugin-yaml/bun.lock index e0ad84ede18494..9f0a5a9bdcb97e 100644 --- a/packages/bun-plugin-yaml/bun.lock +++ b/packages/bun-plugin-yaml/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun-plugin", diff --git a/packages/bun-polyfills/bun.lock b/packages/bun-polyfills/bun.lock index 4d752d144d1139..1dca970ae00ea3 100644 --- a/packages/bun-polyfills/bun.lock +++ b/packages/bun-polyfills/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun-polyfills", @@ -20,6 +20,9 @@ "peerDependencies": { "typescript": "^5.0.0", }, + "optionalPeers": [ + "typescript", + ], }, }, "packages": { diff --git a/packages/bun-release/bun.lock b/packages/bun-release/bun.lock index 7a62c9f905d98a..d0ecb7d5d51542 100644 --- a/packages/bun-release/bun.lock +++ b/packages/bun-release/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { @@ -172,7 +172,7 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "node-fetch": ["node-fetch@2.6.9", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" } }, "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg=="], + "node-fetch": ["node-fetch@2.6.9", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg=="], "octokit": ["octokit@2.0.14", "", { "dependencies": { "@octokit/app": "^13.1.1", "@octokit/core": "^4.0.4", "@octokit/oauth-app": "^4.0.6", "@octokit/plugin-paginate-rest": "^6.0.0", "@octokit/plugin-rest-endpoint-methods": "^7.0.0", "@octokit/plugin-retry": "^4.0.3", "@octokit/plugin-throttling": "^5.0.0", "@octokit/types": "^9.0.0" } }, "sha512-z6cgZBFxirpFEQ1La8Lg83GCs5hOV2EPpkYYdjsGNbfQMv8qUGjq294MiRBCbZqLufviakGsPUxaNKe3JrPmsA=="], diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index 23f1c6d3ba98df..bfe9476bef6aff 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -3734,7 +3734,7 @@ declare module "bun" { port?: string | number; /** - * If the `SO_REUSEPORT` flag should be set. + * Whether the `SO_REUSEPORT` flag should be set. * * This allows multiple processes to bind to the same port, which is useful for load balancing. * @@ -3742,6 +3742,12 @@ declare module "bun" { */ reusePort?: boolean; + /** + * Whether the `IPV6_V6ONLY` flag should be set. + * @default false + */ + ipv6Only?: boolean; + /** * What hostname should the server listen on? * @@ -6972,7 +6978,7 @@ declare module "bun" { * Types for `bun.lock` */ type BunLockFile = { - lockfileVersion: 0; + lockfileVersion: 0 | 1; workspaces: { [workspace: string]: BunLockFileWorkspacePackage; }; @@ -6984,10 +6990,11 @@ declare module "bun" { * ``` * INFO = { prod/dev/optional/peer dependencies, os, cpu, libc (TODO), bin, binDir } * + * // first index is resolution for each type of package * npm -> [ "name@version", registry (TODO: remove if default), INFO, integrity] * symlink -> [ "name@link:path", INFO ] * folder -> [ "name@file:path", INFO ] - * workspace -> [ "name@workspace:path", INFO ] + * workspace -> [ "name@workspace:path" ] // workspace is only path * tarball -> [ "name@tarball", INFO ] * root -> [ "name@root:", { bin, binDir } ] * git -> [ "name@git+repo", INFO, .bun-tag string (TODO: remove this) ] @@ -7005,6 +7012,8 @@ declare module "bun" { optionalDependencies?: Record; peerDependencies?: Record; optionalPeers?: string[]; + bin?: string | Record; + binDir?: string; }; type BunLockFileWorkspacePackage = BunLockFileBasePackageInfo & { @@ -7015,8 +7024,6 @@ declare module "bun" { type BunLockFilePackageInfo = BunLockFileBasePackageInfo & { os?: string | string[]; cpu?: string | string[]; - bin?: Record; - binDir?: string; bundled?: true; }; @@ -7024,10 +7031,12 @@ declare module "bun" { type BunLockFilePackageArray = /** npm */ | [pkg: string, registry: string, info: BunLockFilePackageInfo, integrity: string] - /** symlink, folder, tarball, workspace */ + /** symlink, folder, tarball */ | [pkg: string, info: BunLockFilePackageInfo] + /** workspace */ + | [pkg: string] /** git, github */ | [pkg: string, info: BunLockFilePackageInfo, bunTag: string] /** root */ - | [pkg: string, info: Pick]; + | [pkg: string, info: Pick]; } diff --git a/packages/bun-types/package.json b/packages/bun-types/package.json index 8139546ef74f25..73298a165ece0f 100644 --- a/packages/bun-types/package.json +++ b/packages/bun-types/package.json @@ -27,7 +27,7 @@ }, "scripts": { "prebuild": "echo $(pwd)", - "copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION:-1.0.0}\"'/g' ./docs/**/*.md", + "copy-docs": "rm -rf docs && cp -rL ../../docs/ ./docs && find ./docs -type f -name '*.md' -exec sed -i 's/\\$BUN_LATEST_VERSION/'\"${BUN_VERSION#bun-v:-1.0.0}\"'/g' {} +", "build": "bun run copy-docs && bun scripts/build.ts && bun run fmt", "test": "tsc", "fmt": "echo $(which biome) && biome format --write ." diff --git a/packages/bun-usockets/src/bsd.c b/packages/bun-usockets/src/bsd.c index c11d88495b1c79..5b4e24a1b4b07d 100644 --- a/packages/bun-usockets/src/bsd.c +++ b/packages/bun-usockets/src/bsd.c @@ -387,8 +387,15 @@ int bsd_socket_multicast_interface(LIBUS_SOCKET_DESCRIPTOR fd, const struct sock static int bsd_socket_set_membership4(LIBUS_SOCKET_DESCRIPTOR fd, const struct sockaddr_in *addr, const struct sockaddr_in *iface, int drop) { struct ip_mreq mreq; memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr; - mreq.imr_interface.s_addr = iface->sin_addr.s_addr; + + if (iface != NULL) { + mreq.imr_interface.s_addr = iface->sin_addr.s_addr; + } else { + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } + int option = drop ? IP_DROP_MEMBERSHIP : IP_ADD_MEMBERSHIP; return setsockopt(fd, IPPROTO_IP, option, &mreq, sizeof(mreq)); } @@ -397,13 +404,15 @@ static int bsd_socket_set_membership6(LIBUS_SOCKET_DESCRIPTOR fd, const struct s struct ipv6_mreq mreq; memset(&mreq, 0, sizeof(mreq)); mreq.ipv6mr_multiaddr = addr->sin6_addr; - mreq.ipv6mr_interface = iface->sin6_scope_id; + if (iface != NULL) { + mreq.ipv6mr_interface = iface->sin6_scope_id; + } int option = drop ? IPV6_LEAVE_GROUP : IPV6_JOIN_GROUP; return setsockopt(fd, IPPROTO_IP, option, &mreq, sizeof(mreq)); } int bsd_socket_set_membership(LIBUS_SOCKET_DESCRIPTOR fd, const struct sockaddr_storage *addr, const struct sockaddr_storage *iface, int drop) { - if (addr->ss_family != iface->ss_family) { + if (iface != NULL && addr->ss_family != iface->ss_family) { errno = EINVAL; return -1; } @@ -801,6 +810,66 @@ static int us_internal_bind_and_listen(LIBUS_SOCKET_DESCRIPTOR listenFd, struct return result; } +static int bsd_set_reuseaddr(LIBUS_SOCKET_DESCRIPTOR listenFd) { + const int one = 1; +#if defined(SO_REUSEPORT) && !defined(__linux__) && !defined(__GNU__) + return setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); +#else + return setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); +#endif +} + +static int bsd_set_reuseport(LIBUS_SOCKET_DESCRIPTOR listenFd) { +#if defined(__linux__) + // Among Bun's supported platforms, only Linux does load balancing with SO_REUSEPORT. + const int one = 1; + return setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); +#else +#if _WIN32 + WSASetLastError(WSAEOPNOTSUPP); +#endif + errno = ENOTSUP; + return -1; +#endif +} + +static int bsd_set_reuse(LIBUS_SOCKET_DESCRIPTOR listenFd, int options) { + int result = 0; + + if ((options & LIBUS_LISTEN_EXCLUSIVE_PORT)) { +#if _WIN32 + const int one = 1; + result = setsockopt(listenFd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &one, sizeof(one)); + if (result != 0) { + return result; + } +#endif + } + + if ((options & LIBUS_LISTEN_REUSE_ADDR)) { + result = bsd_set_reuseaddr(listenFd); + if (result != 0) { + return result; + } + } + + if ((options & LIBUS_LISTEN_REUSE_PORT)) { + result = bsd_set_reuseport(listenFd); + if (result != 0) { + if (errno == ENOTSUP) { + if ((options & LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE) == 0) { + errno = 0; + return 0; + } + } + + return result; + } + } + + return 0; +} + inline __attribute__((always_inline)) LIBUS_SOCKET_DESCRIPTOR bsd_bind_listen_fd( LIBUS_SOCKET_DESCRIPTOR listenFd, struct addrinfo *listenAddr, @@ -809,44 +878,26 @@ inline __attribute__((always_inline)) LIBUS_SOCKET_DESCRIPTOR bsd_bind_listen_fd int* error ) { - if ((options & LIBUS_LISTEN_EXCLUSIVE_PORT)) { -#if _WIN32 - int optval2 = 1; - setsockopt(listenFd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &optval2, sizeof(optval2)); -#endif - } else { - if((options & LIBUS_LISTEN_REUSE_PORT)) { - int optval2 = 1; -#if defined(SO_REUSEPORT) - setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, &optval2, sizeof(optval2)); -#else - setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &optval2, sizeof(optval2)); -#endif - } + if (bsd_set_reuse(listenFd, options) != 0) { + return LIBUS_SOCKET_ERROR; } -#if defined(SO_REUSEADDR) - #ifndef _WIN32 - +#if defined(SO_REUSEADDR) && !_WIN32 // Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just // allow binding to addresses that are in use by sockets in TIME_WAIT, it // effectively allows 'stealing' a port which is in use by another application. // See libuv issue #1360. - - - int optval3 = 1; - setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &optval3, sizeof(optval3)); - #endif + int one = 1; + setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); #endif #ifdef IPV6_V6ONLY - // TODO: revise support to match node.js - // if (listenAddr->ai_family == AF_INET6) { - // int disabled = (options & LIBUS_SOCKET_IPV6_ONLY) != 0; - // setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, &disabled, sizeof(disabled)); - // } - int disabled = 0; - setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, &disabled, sizeof(disabled)); + if (listenAddr->ai_family == AF_INET6) { + int enabled = (options & LIBUS_SOCKET_IPV6_ONLY) != 0; + if (setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, &enabled, sizeof(enabled)) != 0) { + return LIBUS_SOCKET_ERROR; + } + } #endif if (us_internal_bind_and_listen(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen, 512, error)) { @@ -1105,26 +1156,17 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port, int op setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)); } - if ((options & LIBUS_LISTEN_EXCLUSIVE_PORT)) { -#if _WIN32 - int optval2 = 1; - setsockopt(listenFd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &optval2, sizeof(optval2)); -#endif - } else { - if((options & LIBUS_LISTEN_REUSE_PORT)) { - int optval2 = 1; -#if defined(SO_REUSEPORT) - setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, &optval2, sizeof(optval2)); -#else - setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &optval2, sizeof(optval2)); -#endif - } + if (bsd_set_reuse(listenFd, options) != 0) { + freeaddrinfo(result); + return LIBUS_SOCKET_ERROR; } #ifdef IPV6_V6ONLY if (listenAddr->ai_family == AF_INET6) { - int disabled = (options & LIBUS_SOCKET_IPV6_ONLY) != 0; - setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, &disabled, sizeof(disabled)); + int enabled = (options & LIBUS_SOCKET_IPV6_ONLY) != 0; + if (setsockopt(listenFd, IPPROTO_IPV6, IPV6_V6ONLY, &enabled, sizeof(enabled)) != 0) { + return LIBUS_SOCKET_ERROR; + } } #endif diff --git a/packages/bun-usockets/src/eventing/epoll_kqueue.c b/packages/bun-usockets/src/eventing/epoll_kqueue.c index 612a3a859110b7..cc93b6cba6b55b 100644 --- a/packages/bun-usockets/src/eventing/epoll_kqueue.c +++ b/packages/bun-usockets/src/eventing/epoll_kqueue.c @@ -247,7 +247,7 @@ void us_loop_run(struct us_loop_t *loop) { } } -extern int Bun__JSC_onBeforeWait(void*); +extern void Bun__JSC_onBeforeWait(void*); extern void Bun__JSC_onAfterWait(void*); void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout) { @@ -265,10 +265,8 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout /* Emit pre callback */ us_internal_loop_pre(loop); - int needs_after_wait = 0; - if (loop->data.jsc_vm) { - needs_after_wait = Bun__JSC_onBeforeWait(loop->data.jsc_vm); - } + /* Safe if jsc_vm is NULL */ + Bun__JSC_onBeforeWait(loop->data.jsc_vm); /* Fetch ready polls */ #ifdef LIBUS_USE_EPOLL @@ -280,9 +278,7 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, const struct timespec* timeout } while (IS_EINTR(loop->num_ready_polls)); #endif - if (needs_after_wait) { - Bun__JSC_onAfterWait(loop->data.jsc_vm); - } + 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/libusockets.h b/packages/bun-usockets/src/libusockets.h index dd27d70eeebc56..25707af5327b91 100644 --- a/packages/bun-usockets/src/libusockets.h +++ b/packages/bun-usockets/src/libusockets.h @@ -100,6 +100,8 @@ enum { LIBUS_LISTEN_REUSE_PORT = 4, /* Setting ipv6Only will disable dual-stack support, i.e., binding to host :: won't make 0.0.0.0 be bound.*/ LIBUS_SOCKET_IPV6_ONLY = 8, + LIBUS_LISTEN_REUSE_ADDR = 16, + LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE = 32, }; /* Library types publicly available */ diff --git a/packages/bun-vscode/bun.lock b/packages/bun-vscode/bun.lock index eb359c2e738cda..f1f4f941ccc9fd 100644 --- a/packages/bun-vscode/bun.lock +++ b/packages/bun-vscode/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "mock-debug", @@ -148,9 +148,9 @@ "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], - "bun-debug-adapter-protocol": ["bun-debug-adapter-protocol@workspace:../bun-debug-adapter-protocol", { "dependencies": { "semver": "^7.5.4", "source-map-js": "^1.0.2" } }], + "bun-debug-adapter-protocol": ["bun-debug-adapter-protocol@workspace:../bun-debug-adapter-protocol"], - "bun-inspector-protocol": ["bun-inspector-protocol@workspace:../bun-inspector-protocol", { "dependencies": { "ws": "^8.13.0" } }], + "bun-inspector-protocol": ["bun-inspector-protocol@workspace:../bun-inspector-protocol"], "bun-types": ["bun-types@1.1.29", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-En3/TzSPMPyl5UlUB1MHzHpcrZDakTm7mS203eLoX1fBoEa3PW+aSS8GAqVJ7Is/m34Z5ogL+ECniLY0uDaCPw=="], @@ -516,7 +516,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@8.13.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA=="], + "ws": ["ws@8.13.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA=="], "xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], diff --git a/packages/bun-vscode/example/bun.lock b/packages/bun-vscode/example/bun.lock index 9b42110d976c72..215e27f2e01ea1 100644 --- a/packages/bun-vscode/example/bun.lock +++ b/packages/bun-vscode/example/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { @@ -20,6 +20,9 @@ "peerDependencies": { "typescript": "^5.0.0", }, + "optionalPeers": [ + "typescript", + ], }, }, "trustedDependencies": [ diff --git a/packages/bun-wasm/bun.lock b/packages/bun-wasm/bun.lock index 65f16aae55d221..6ab528a9113e36 100644 --- a/packages/bun-wasm/bun.lock +++ b/packages/bun-wasm/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun-wasm", diff --git a/root_wasm.zig b/root_wasm.zig index 7865cc04719e2b..a136835f2b3a45 100644 --- a/root_wasm.zig +++ b/root_wasm.zig @@ -3,7 +3,6 @@ pub usingnamespace @import("src/main_wasm.zig"); pub const bun = @import("src/bun.zig"); pub const completions = struct {}; -pub const is_bindgen = true; pub const JavaScriptCore = struct { pub fn markBinding(_: @import("std").builtin.SourceLocation) void { unreachable; diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index f5f793fa3aa2a8..309b3d5af4715c 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -765,7 +765,7 @@ install_nodejs_headers() { } bun_version_exact() { - print "1.1.38" + print "1.2.0" } install_bun() { diff --git a/src/Global.zig b/src/Global.zig index f935d3b958c3a9..0a07e0ec8f56c8 100644 --- a/src/Global.zig +++ b/src/Global.zig @@ -170,13 +170,13 @@ pub inline fn configureAllocator(_: AllocatorConfiguration) void { } pub fn notimpl() noreturn { - @setCold(true); + @branchHint(.cold); Output.panic("Not implemented yet!!!!!", .{}); } // Make sure we always print any leftover pub fn crash() noreturn { - @setCold(true); + @branchHint(.cold); Global.exit(1); } diff --git a/src/Mutex.zig b/src/Mutex.zig index 7e824f2d822a9b..0aaaee366d3e72 100644 --- a/src/Mutex.zig +++ b/src/Mutex.zig @@ -164,7 +164,7 @@ const FutexImpl = struct { } fn lockSlow(self: *@This()) void { - @setCold(true); + @branchHint(.cold); // Avoid doing an atomic swap below if we already know the state is contended. // An atomic swap unconditionally stores which marks the cache-line as modified unnecessarily. diff --git a/src/Watcher.zig b/src/Watcher.zig index 7639bc11bed75f..3f710c64ceb354 100644 --- a/src/Watcher.zig +++ b/src/Watcher.zig @@ -333,11 +333,11 @@ fn appendFileAssumeCapacity( // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html var event = std.mem.zeroes(KEvent); - event.flags = std.c.EV_ADD | std.c.EV_CLEAR | std.c.EV_ENABLE; + event.flags = std.c.EV.ADD | std.c.EV.CLEAR | std.c.EV.ENABLE; // we want to know about the vnode - event.filter = std.c.EVFILT_VNODE; + event.filter = std.c.EVFILT.VNODE; - event.fflags = std.c.NOTE_WRITE | std.c.NOTE_RENAME | std.c.NOTE_DELETE; + event.fflags = std.c.NOTE.WRITE | std.c.NOTE.RENAME | std.c.NOTE.DELETE; // id event.ident = @intCast(fd.int()); @@ -425,15 +425,15 @@ fn appendDirectoryAssumeCapacity( // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html var event = std.mem.zeroes(KEvent); - event.flags = std.c.EV_ADD | std.c.EV_CLEAR | std.c.EV_ENABLE; + event.flags = std.c.EV.ADD | std.c.EV.CLEAR | std.c.EV.ENABLE; // we want to know about the vnode - event.filter = std.c.EVFILT_VNODE; + event.filter = std.c.EVFILT.VNODE; // monitor: // - Write // - Rename // - Delete - event.fflags = std.c.NOTE_WRITE | std.c.NOTE_RENAME | std.c.NOTE_DELETE; + event.fflags = std.c.NOTE.WRITE | std.c.NOTE.RENAME | std.c.NOTE.DELETE; // id event.ident = @intCast(fd.int()); diff --git a/src/analytics/analytics_thread.zig b/src/analytics/analytics_thread.zig index d8c77de1eda461..e0d3dfcc902460 100644 --- a/src/analytics/analytics_thread.zig +++ b/src/analytics/analytics_thread.zig @@ -20,7 +20,7 @@ const Analytics = @import("./analytics_schema.zig").analytics; const Writer = @import("./analytics_schema.zig").Writer; const Headers = bun.http.Headers; const Futex = @import("../futex.zig"); -const Semver = @import("../install/semver.zig"); +const Semver = bun.Semver; /// Enables analytics. This is used by: /// - crash_handler.zig's `report` function to anonymously report crashes @@ -122,10 +122,12 @@ pub const Features = struct { pub var workers_terminated: usize = 0; pub var napi_module_register: usize = 0; pub var process_dlopen: usize = 0; + pub var postgres_connections: usize = 0; + pub var s3: usize = 0; comptime { - @export(napi_module_register, .{ .name = "Bun__napi_module_register_count" }); - @export(process_dlopen, .{ .name = "Bun__process_dlopen_count" }); + @export(&napi_module_register, .{ .name = "Bun__napi_module_register_count" }); + @export(&process_dlopen, .{ .name = "Bun__process_dlopen_count" }); } pub fn formatter() Formatter { @@ -136,14 +138,14 @@ pub const Features = struct { pub fn format(_: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { const fields = comptime brk: { const info: std.builtin.Type = @typeInfo(Features); - var buffer: [info.Struct.decls.len][]const u8 = .{""} ** info.Struct.decls.len; + var buffer: [info.@"struct".decls.len][]const u8 = .{""} ** info.@"struct".decls.len; var count: usize = 0; - for (info.Struct.decls) |decl| { + for (info.@"struct".decls) |decl| { var f = &@field(Features, decl.name); _ = &f; const Field = @TypeOf(f); const FieldT: std.builtin.Type = @typeInfo(Field); - if (FieldT.Pointer.child != usize) continue; + if (FieldT.pointer.child != usize) continue; buffer[count] = decl.name; count += 1; } @@ -214,7 +216,7 @@ pub const packed_features_list = brk: { }; pub const PackedFeatures = @Type(.{ - .Struct = .{ + .@"struct" = .{ .layout = .@"packed", .backing_integer = u64, .fields = brk: { @@ -224,7 +226,7 @@ pub const PackedFeatures = @Type(.{ fields[i] = .{ .name = name, .type = bool, - .default_value = &false, + .default_value_ptr = &false, .is_comptime = false, .alignment = 0, }; @@ -234,7 +236,7 @@ pub const PackedFeatures = @Type(.{ fields[i] = .{ .name = std.fmt.comptimePrint("_{d}", .{i}), .type = bool, - .default_value = &false, + .default_value_ptr = &false, .is_comptime = false, .alignment = 0, }; diff --git a/src/api/bun.lock b/src/api/bun.lock index c1a969ec13d62d..385da39f6bcf7b 100644 --- a/src/api/bun.lock +++ b/src/api/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "bun-api", diff --git a/src/api/schema.zig b/src/api/schema.zig index 27fd50e7b9cd44..163a1a76131aeb 100644 --- a/src/api/schema.zig +++ b/src/api/schema.zig @@ -1702,6 +1702,9 @@ pub const Api = struct { /// [serve.static] /// plugins = ["tailwindcss"] serve_plugins: ?[]const []const u8 = null, + serve_minify_syntax: ?bool = null, + serve_minify_whitespace: ?bool = null, + serve_minify_identifiers: ?bool = null, bunfig_path: []const u8, pub fn decode(reader: anytype) anyerror!TransformOptions { diff --git a/src/ast/base.zig b/src/ast/base.zig index ffd6240ad3e3ba..de1f8a5a3f3d20 100644 --- a/src/ast/base.zig +++ b/src/ast/base.zig @@ -62,7 +62,7 @@ pub const Index = packed struct(u32) { pub fn init(num: anytype) Index { const NumType = @TypeOf(num); - if (comptime @typeInfo(NumType) == .Pointer) { + if (comptime @typeInfo(NumType) == .pointer) { return init(num.*); } diff --git a/src/async/posix_event_loop.zig b/src/async/posix_event_loop.zig index 2dfb108952fae8..7ee6c5d31d362c 100644 --- a/src/async/posix_event_loop.zig +++ b/src/async/posix_event_loop.zig @@ -366,42 +366,42 @@ pub const FilePoll = struct { // var loader = ptr.as(ShellSubprocessCapturedBufferedWriterMini); // loader.onPoll(size_or_offset, 0); // }, - @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellBufferedWriter))) => { + @field(Owner.Tag, @typeName(ShellBufferedWriter)) => { var handler: *ShellBufferedWriter = ptr.as(ShellBufferedWriter); handler.onPoll(size_or_offset, poll.flags.contains(.hup)); }, - @field(Owner.Tag, bun.meta.typeBaseName(@typeName(ShellStaticPipeWriter))) => { + @field(Owner.Tag, @typeName(ShellStaticPipeWriter)) => { var handler: *ShellStaticPipeWriter = ptr.as(ShellStaticPipeWriter); handler.onPoll(size_or_offset, poll.flags.contains(.hup)); }, - @field(Owner.Tag, bun.meta.typeBaseName(@typeName(StaticPipeWriter))) => { + @field(Owner.Tag, @typeName(StaticPipeWriter)) => { var handler: *StaticPipeWriter = ptr.as(StaticPipeWriter); handler.onPoll(size_or_offset, poll.flags.contains(.hup)); }, - @field(Owner.Tag, bun.meta.typeBaseName(@typeName(FileSink))) => { + @field(Owner.Tag, @typeName(FileSink)) => { var handler: *FileSink = ptr.as(FileSink); handler.onPoll(size_or_offset, poll.flags.contains(.hup)); }, - @field(Owner.Tag, bun.meta.typeBaseName(@typeName(BufferedReader))) => { + @field(Owner.Tag, @typeName(BufferedReader)) => { log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) Reader", .{poll.fd}); var handler: *BufferedReader = ptr.as(BufferedReader); handler.onPoll(size_or_offset, poll.flags.contains(.hup)); }, - @field(Owner.Tag, bun.meta.typeBaseName(@typeName(Process))) => { + @field(Owner.Tag, @typeName(Process)) => { log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) Process", .{poll.fd}); var loader = ptr.as(Process); loader.onWaitPidFromEventLoopTask(); }, - @field(Owner.Tag, "DNSResolver") => { + @field(Owner.Tag, @typeName(DNSResolver)) => { log("onUpdate " ++ kqueue_or_epoll ++ " (fd: {}) DNSResolver", .{poll.fd}); var loader: *DNSResolver = ptr.as(DNSResolver); loader.onDNSPoll(poll); }, - @field(Owner.Tag, "GetAddrInfoRequest") => { + @field(Owner.Tag, @typeName(GetAddrInfoRequest)) => { if (comptime !Environment.isMac) { unreachable; } @@ -411,7 +411,7 @@ pub const FilePoll = struct { loader.onMachportChange(); }, - @field(Owner.Tag, "Request") => { + @field(Owner.Tag, @typeName(Request)) => { if (comptime !Environment.isMac) { unreachable; } @@ -503,19 +503,19 @@ pub const FilePoll = struct { pub fn fromKQueueEvent(kqueue_event: std.posix.system.kevent64_s) Flags.Set { var flags = Flags.Set{}; - if (kqueue_event.filter == std.posix.system.EVFILT_READ) { + if (kqueue_event.filter == std.posix.system.EVFILT.READ) { flags.insert(Flags.readable); - if (kqueue_event.flags & std.posix.system.EV_EOF != 0) { + if (kqueue_event.flags & std.posix.system.EV.EOF != 0) { flags.insert(Flags.hup); } - } else if (kqueue_event.filter == std.posix.system.EVFILT_WRITE) { + } else if (kqueue_event.filter == std.posix.system.EVFILT.WRITE) { flags.insert(Flags.writable); - if (kqueue_event.flags & std.posix.system.EV_EOF != 0) { + if (kqueue_event.flags & std.posix.system.EV.EOF != 0) { flags.insert(Flags.hup); } - } else if (kqueue_event.filter == std.posix.system.EVFILT_PROC) { + } else if (kqueue_event.filter == std.posix.system.EVFILT.PROC) { flags.insert(Flags.process); - } else if (kqueue_event.filter == std.posix.system.EVFILT_MACHPORT) { + } else if (kqueue_event.filter == std.posix.system.EVFILT.MACHPORT) { flags.insert(Flags.machport); } return flags; @@ -592,8 +592,10 @@ pub const FilePoll = struct { poll.flags.insert(.ignore_updates); this.pending_free_tail = poll; - bun.assert(vm.after_event_loop_callback == null or vm.after_event_loop_callback == @as(?JSC.OpaqueCallback, @ptrCast(&processDeferredFrees))); - vm.after_event_loop_callback = @ptrCast(&processDeferredFrees); + + const callback = JSC.OpaqueWrap(Store, processDeferredFrees); + bun.assert(vm.after_event_loop_callback == null or vm.after_event_loop_callback == @as(?JSC.OpaqueCallback, callback)); + vm.after_event_loop_callback = callback; vm.after_event_loop_callback_ctx = this; } }; @@ -763,7 +765,7 @@ pub const FilePoll = struct { pub fn onTick(loop: *Loop, tagged_pointer: ?*anyopaque) callconv(.C) void { var tag = Pollable.from(tagged_pointer); - if (tag.tag() != @field(Pollable.Tag, "FilePoll")) + if (tag.tag() != @field(Pollable.Tag, @typeName(FilePoll))) return; var file_poll: *FilePoll = tag.as(FilePoll); @@ -782,7 +784,7 @@ pub const FilePoll = struct { }); comptime { - @export(onTick, .{ .name = "Bun__internal_dispatch_ready_poll" }); + @export(&onTick, .{ .name = "Bun__internal_dispatch_ready_poll" }); } const timeout = std.mem.zeroes(std.posix.timespec); @@ -837,45 +839,45 @@ pub const FilePoll = struct { const one_shot_flag: u16 = if (!this.flags.contains(.one_shot)) 0 else if (one_shot == .dispatch) - std.c.EV_DISPATCH | std.c.EV_ENABLE + std.c.EV.DISPATCH | std.c.EV.ENABLE else - std.c.EV_ONESHOT; + std.c.EV.ONESHOT; changelist[0] = switch (flag) { .readable => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_READ, + .filter = std.posix.system.EVFILT.READ, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_ADD | one_shot_flag, + .flags = std.c.EV.ADD | one_shot_flag, .ext = .{ this.generation_number, 0 }, }, .writable => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_WRITE, + .filter = std.posix.system.EVFILT.WRITE, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_ADD | one_shot_flag, + .flags = std.c.EV.ADD | one_shot_flag, .ext = .{ this.generation_number, 0 }, }, .process => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_PROC, + .filter = std.posix.system.EVFILT.PROC, .data = 0, - .fflags = std.c.NOTE_EXIT, + .fflags = std.c.NOTE.EXIT, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_ADD | one_shot_flag, + .flags = std.c.EV.ADD | one_shot_flag, .ext = .{ this.generation_number, 0 }, }, .machport => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_MACHPORT, + .filter = std.posix.system.EVFILT.MACHPORT, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_ADD | one_shot_flag, + .flags = std.c.EV.ADD | one_shot_flag, .ext = .{ this.generation_number, 0 }, }, else => unreachable, @@ -913,7 +915,7 @@ pub const FilePoll = struct { // processing an element of the changelist and there is enough room // in the eventlist, then the event will be placed in the eventlist // with EV_ERROR set in flags and the system error in data. - if (changelist[0].flags == std.c.EV_ERROR and changelist[0].data != 0) { + if (changelist[0].flags == std.c.EV.ERROR and changelist[0].data != 0) { return JSC.Maybe(void).errnoSys(changelist[0].data, .kevent).?; // Otherwise, -1 will be returned, and errno will be set to // indicate the error condition. @@ -1008,38 +1010,38 @@ pub const FilePoll = struct { changelist[0] = switch (flag) { .readable => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_READ, + .filter = std.posix.system.EVFILT.READ, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_DELETE, + .flags = std.c.EV.DELETE, .ext = .{ 0, 0 }, }, .machport => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_MACHPORT, + .filter = std.posix.system.EVFILT.MACHPORT, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_DELETE, + .flags = std.c.EV.DELETE, .ext = .{ 0, 0 }, }, .writable => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_WRITE, + .filter = std.posix.system.EVFILT.WRITE, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_DELETE, + .flags = std.c.EV.DELETE, .ext = .{ 0, 0 }, }, .process => .{ .ident = @intCast(fd.cast()), - .filter = std.posix.system.EVFILT_PROC, + .filter = std.posix.system.EVFILT.PROC, .data = 0, - .fflags = std.c.NOTE_EXIT, + .fflags = std.c.NOTE.EXIT, .udata = @intFromPtr(Pollable.init(this).ptr()), - .flags = std.c.EV_DELETE, + .flags = std.c.EV.DELETE, .ext = .{ 0, 0 }, }, else => unreachable, @@ -1065,7 +1067,7 @@ pub const FilePoll = struct { // processing an element of the changelist and there is enough room // in the eventlist, then the event will be placed in the eventlist // with EV_ERROR set in flags and the system error in data. - if (changelist[0].flags == std.c.EV_ERROR) { + if (changelist[0].flags == std.c.EV.ERROR) { return JSC.Maybe(void).errnoSys(changelist[0].data, .kevent).?; // Otherwise, -1 will be returned, and errno will be set to // indicate the error condition. diff --git a/src/async/windows_event_loop.zig b/src/async/windows_event_loop.zig index 0943d1959b1938..6ac815a8494808 100644 --- a/src/async/windows_event_loop.zig +++ b/src/async/windows_event_loop.zig @@ -358,8 +358,10 @@ pub const FilePoll = struct { poll.flags.insert(.ignore_updates); this.pending_free_tail = poll; - bun.assert(vm.after_event_loop_callback == null or vm.after_event_loop_callback == @as(?JSC.OpaqueCallback, @ptrCast(&processDeferredFrees))); - vm.after_event_loop_callback = @ptrCast(&processDeferredFrees); + + const callback = JSC.OpaqueWrap(Store, processDeferredFrees); + bun.assert(vm.after_event_loop_callback == null or vm.after_event_loop_callback == @as(?JSC.OpaqueCallback, callback)); + vm.after_event_loop_callback = callback; vm.after_event_loop_callback_ctx = this; } }; diff --git a/src/baby_list.zig b/src/baby_list.zig index 4db8655638a2b1..a6ff5f63bf2210 100644 --- a/src/baby_list.zig +++ b/src/baby_list.zig @@ -342,7 +342,7 @@ pub fn BabyList(comptime Type: type) type { return this.len - initial; } - pub fn writeLatin1(this: *@This(), allocator: std.mem.Allocator, str: []const u8) !u32 { + pub fn writeLatin1(this: *@This(), allocator: std.mem.Allocator, str: []const u8) OOM!u32 { if (comptime Type != u8) @compileError("Unsupported for type " ++ @typeName(Type)); const initial = this.len; @@ -352,7 +352,7 @@ pub fn BabyList(comptime Type: type) type { return this.len - initial; } - pub fn writeUTF16(this: *@This(), allocator: std.mem.Allocator, str: []const u16) !u32 { + pub fn writeUTF16(this: *@This(), allocator: std.mem.Allocator, str: []const u16) OOM!u32 { if (comptime Type != u8) @compileError("Unsupported for type " ++ @typeName(Type)); diff --git a/src/bake/BakeGlobalObject.cpp b/src/bake/BakeGlobalObject.cpp index 2e3df0c2de1ba1..efa663385904d3 100644 --- a/src/bake/BakeGlobalObject.cpp +++ b/src/bake/BakeGlobalObject.cpp @@ -21,13 +21,13 @@ bakeModuleLoaderImportModule(JSC::JSGlobalObject* global, { WTF::String keyString = moduleNameValue->getString(global); if (keyString.startsWith("bake:/"_s)) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); return JSC::importModule(global, JSC::Identifier::fromString(vm, keyString), JSC::jsUndefined(), parameters, JSC::jsUndefined()); } if (!sourceOrigin.isNull() && sourceOrigin.string().startsWith("bake:/"_s)) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_THROW_SCOPE(vm); WTF::String refererString = sourceOrigin.string(); @@ -55,7 +55,7 @@ JSC::Identifier bakeModuleLoaderResolve(JSC::JSGlobalObject* jsGlobal, JSC::JSValue referrer, JSC::JSValue origin) { Bake::GlobalObject* global = jsCast(jsGlobal); - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_THROW_SCOPE(vm); ASSERT(referrer.isString()); @@ -77,7 +77,7 @@ JSC::Identifier bakeModuleLoaderResolve(JSC::JSGlobalObject* jsGlobal, static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, JSC::jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast(JSC::JSPromise::Status::Rejected))); @@ -86,7 +86,7 @@ static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* glob static JSC::JSInternalPromise* resolvedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSInternalPromise* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, JSC::jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast(JSC::JSPromise::Status::Fulfilled))); @@ -100,7 +100,7 @@ JSC::JSInternalPromise* bakeModuleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::JSValue parameters, JSC::JSValue script) { Bake::GlobalObject* global = jsCast(globalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto moduleKey = key.toWTFString(globalObject); if (UNLIKELY(scope.exception())) diff --git a/src/bake/BakeProduction.cpp b/src/bake/BakeProduction.cpp index 1db8e9ee5b8021..5d2a86720072d2 100644 --- a/src/bake/BakeProduction.cpp +++ b/src/bake/BakeProduction.cpp @@ -21,7 +21,7 @@ extern "C" JSC::JSPromise* BakeRenderRoutesForProdStatic( JSC::JSValue paramInformation, JSC::JSValue styles) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); JSC::JSFunction* cb = JSC::JSFunction::create(vm, global, WebCore::bakeRenderRoutesForProdStaticCodeGenerator(vm), global); JSC::CallData callData = JSC::getCallData(cb); diff --git a/src/bake/BakeSourceProvider.cpp b/src/bake/BakeSourceProvider.cpp index 2b1c4a9d14e6d0..10e2175887974b 100644 --- a/src/bake/BakeSourceProvider.cpp +++ b/src/bake/BakeSourceProvider.cpp @@ -17,7 +17,7 @@ namespace Bake { extern "C" JSC::EncodedJSValue BakeLoadInitialServerCode(GlobalObject* global, BunString source, bool separateSSRGraph) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_THROW_SCOPE(vm); String string = "bake://server-runtime.js"_s; @@ -75,7 +75,7 @@ extern "C" JSC::EncodedJSValue BakeGetModuleNamespace( JSC::JSValue keyValue ) { JSC::JSString* key = JSC::jsCast(keyValue); - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); JSC::JSMap* map = JSC::jsCast( global->moduleLoader()->getDirect( vm, JSC::Identifier::fromString(global->vm(), "registry"_s) @@ -93,7 +93,7 @@ extern "C" JSC::EncodedJSValue BakeGetDefaultExportFromModule( JSC::JSGlobalObject* global, JSC::JSValue keyValue ) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); return JSC::JSValue::encode(jsCast(JSC::JSValue::decode(BakeGetModuleNamespace(global, keyValue)))->get(global, vm.propertyNames->defaultKeyword)); } @@ -104,7 +104,7 @@ extern "C" JSC::EncodedJSValue BakeGetOnModuleNamespace( const unsigned char* key, size_t keyLength ) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); const auto propertyString = String(StringImpl::createWithoutCopying({ key, keyLength })); const auto identifier = JSC::Identifier::fromString(vm, propertyString); const auto property = JSC::PropertyName(identifier); @@ -112,7 +112,7 @@ extern "C" JSC::EncodedJSValue BakeGetOnModuleNamespace( } extern "C" JSC::EncodedJSValue BakeRegisterProductionChunk(JSC::JSGlobalObject* global, BunString virtualPathName, BunString source) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_THROW_SCOPE(vm); String string = virtualPathName.toWTFString(); diff --git a/src/bake/DevServer.zig b/src/bake/DevServer.zig index 04a8d5f23b714a..6b7f957926d542 100644 --- a/src/bake/DevServer.zig +++ b/src/bake/DevServer.zig @@ -865,7 +865,7 @@ const DeferredRequest = struct { server_handler: bun.JSC.API.SavedRequest, js_payload: *Response, - const Tag = @typeInfo(Data).Union.tag_type.?; + const Tag = @typeInfo(Data).@"union".tag_type.?; }; }; @@ -3715,20 +3715,20 @@ const HmrTopic = enum(u8) { /// Invalid data _, - pub const max_count = @typeInfo(HmrTopic).Enum.fields.len; - pub const Bits = @Type(.{ .Struct = .{ - .backing_integer = @Type(.{ .Int = .{ + pub const max_count = @typeInfo(HmrTopic).@"enum".fields.len; + pub const Bits = @Type(.{ .@"struct" = .{ + .backing_integer = @Type(.{ .int = .{ .bits = max_count, .signedness = .unsigned, } }), .fields = &brk: { - const enum_fields = @typeInfo(HmrTopic).Enum.fields; + const enum_fields = @typeInfo(HmrTopic).@"enum".fields; var fields: [enum_fields.len]std.builtin.Type.StructField = undefined; for (enum_fields, &fields) |e, *s| { s.* = .{ .name = e.name, .type = bool, - .default_value = &false, + .default_value_ptr = &false, .is_comptime = false, .alignment = 0, }; @@ -3768,7 +3768,7 @@ const HmrSocket = struct { const topics = msg[1..]; if (topics.len > HmrTopic.max_count) return; outer: for (topics) |char| { - inline for (@typeInfo(HmrTopic).Enum.fields) |field| { + inline for (@typeInfo(HmrTopic).@"enum".fields) |field| { if (char == field.value) { @field(new_bits, field.name) = true; continue :outer; @@ -4063,7 +4063,7 @@ const WatcherAtomics = struct { ev.timer = std.time.Timer.start() catch unreachable; }, 1 => { - // @branchHint(.unlikely); + @branchHint(.unlikely); // DevServer stole this event. Unlikely but possible when // the user is saving very heavily (10-30 times per second) state.current +%= 1; @@ -4087,12 +4087,12 @@ const WatcherAtomics = struct { ev.owner.bun_watcher.thread_lock.assertLocked(); if (ev.files.count() > 0) { - // @branchHint(.likely); + @branchHint(.likely); // There are files to be processed, increment this count first. const prev_count = state.watcher_events_emitted.fetchAdd(1, .seq_cst); if (prev_count == 0) { - // @branchHint(.likely); + @branchHint(.likely); // Submit a task to the DevServer, notifying it that there is // work to do. The watcher will move to the other event. ev.concurrent_task = .{ @@ -4434,7 +4434,7 @@ pub const EntryPointList = struct { pub fn append(entry_points: *EntryPointList, allocator: std.mem.Allocator, abs_path: []const u8, flags: Flags) !void { const gop = try entry_points.set.getOrPut(allocator, abs_path); if (gop.found_existing) { - const T = @typeInfo(Flags).Struct.backing_integer.?; + const T = @typeInfo(Flags).@"struct".backing_integer.?; gop.value_ptr.* = @bitCast(@as(T, @bitCast(gop.value_ptr.*)) | @as(T, @bitCast(flags))); } else { gop.value_ptr.* = flags; diff --git a/src/bake/FrameworkRouter.zig b/src/bake/FrameworkRouter.zig index bab239a9f69e29..3182e8ca7c594a 100644 --- a/src/bake/FrameworkRouter.zig +++ b/src/bake/FrameworkRouter.zig @@ -331,7 +331,7 @@ pub const Part = union(enum(u3)) { group: []const u8, const SerializedHeader = packed struct(u32) { - tag: @typeInfo(Part).Union.tag_type.?, + tag: @typeInfo(Part).@"union".tag_type.?, len: u29, }; @@ -1246,7 +1246,7 @@ pub const JSFrameworkRouter = struct { return global.throwInvalidArguments("parseRoutePattern takes two arguments", .{}); const style_js, const filepath_js = frame.argumentsAsArray(2); - const filepath = try filepath_js.toSlice2(global, alloc); + const filepath = try filepath_js.toSlice(global, alloc); defer filepath.deinit(); var style = try Style.fromJS(style_js, global); errdefer style.deinit(); diff --git a/src/bake/bake.zig b/src/bake/bake.zig index f1ce98756824a9..5bd4a162434ca7 100644 --- a/src/bake/bake.zig +++ b/src/bake/bake.zig @@ -458,7 +458,7 @@ pub const Framework = struct { const extensions: []const []const u8 = if (try fsr_opts.get(global, "extensions")) |exts_js| exts: { if (exts_js.isString()) { - const str = try exts_js.toSlice2(global, arena); + const str = try exts_js.toSlice(global, arena); defer str.deinit(); if (bun.strings.eqlComptime(str.slice(), "*")) { break :exts &.{}; @@ -468,7 +468,7 @@ pub const Framework = struct { var i_2: usize = 0; const extensions = try arena.alloc([]const u8, exts_js.getLength(global)); while (it_2.next()) |array_item| : (i_2 += 1) { - const slice = refs.track(try array_item.toSlice2(global, arena)); + const slice = refs.track(try array_item.toSlice(global, arena)); if (bun.strings.eqlComptime(slice, "*")) return global.throwInvalidArguments("'extensions' cannot include \"*\" as an extension. Pass \"*\" instead of the array.", .{}); @@ -493,7 +493,7 @@ pub const Framework = struct { var i_2: usize = 0; const dirs = try arena.alloc([]const u8, len); while (it_2.next()) |array_item| : (i_2 += 1) { - dirs[i_2] = refs.track(try array_item.toSlice2(global, arena)); + dirs[i_2] = refs.track(try array_item.toSlice(global, arena)); } break :exts dirs; } diff --git a/src/bit_set.zig b/src/bit_set.zig index 2ecd5b3591f12d..f702915dfbe581 100644 --- a/src/bit_set.zig +++ b/src/bit_set.zig @@ -325,10 +325,10 @@ pub fn ArrayBitSet(comptime MaskIntType: type, comptime size: usize) type { const mask_info: std.builtin.Type = @typeInfo(MaskIntType); // Make sure the mask int is indeed an int - if (mask_info != .Int) @compileError("ArrayBitSet can only operate on integer masks, but was passed " ++ @typeName(MaskIntType)); + if (mask_info != .int) @compileError("ArrayBitSet can only operate on integer masks, but was passed " ++ @typeName(MaskIntType)); // It must also be unsigned. - if (mask_info.Int.signedness != .unsigned) @compileError("ArrayBitSet requires an unsigned integer mask type, but was passed " ++ @typeName(MaskIntType)); + if (mask_info.int.signedness != .unsigned) @compileError("ArrayBitSet requires an unsigned integer mask type, but was passed " ++ @typeName(MaskIntType)); // And it must not be empty. if (MaskIntType == u0) @@ -1620,7 +1620,7 @@ fn testSupersetOf(empty: anytype, full: anytype, even: anytype, odd: anytype, le fn testBitSet(a: anytype, b: anytype, len: usize) !void { try testing.expectEqual(len, a.capacity()); try testing.expectEqual(len, b.capacity()); - const needs_ptr = @hasField(std.meta.Child(@TypeOf(a)), "masks") and @typeInfo(@TypeOf(@field(a, "masks"))) != .Pointer; + const needs_ptr = @hasField(std.meta.Child(@TypeOf(a)), "masks") and @typeInfo(@TypeOf(@field(a, "masks"))) != .pointer; { for (0..len) |i| { @@ -1844,7 +1844,7 @@ fn fillOdd(set: anytype, len: usize) void { fn testPureBitSet(comptime Set: type) !void { var empty_ = Set.initEmpty(); var full_ = Set.initFull(); - const needs_ptr = @hasField(Set, "masks") and @typeInfo(@TypeOf(empty_.masks)) != .Pointer; + const needs_ptr = @hasField(Set, "masks") and @typeInfo(@TypeOf(empty_.masks)) != .pointer; var even_ = even: { var bit_set = Set.initEmpty(); @@ -1900,7 +1900,7 @@ fn testPureBitSet(comptime Set: type) !void { try testing.expect(full.differenceWith(even).eql(odd)); } -fn testStaticBitSet(comptime Set: type, comptime Container: @Type(.EnumLiteral)) !void { +fn testStaticBitSet(comptime Set: type, comptime Container: @Type(.enum_literal)) !void { var a = Set.initEmpty(); var b = Set.initFull(); try testing.expectEqual(@as(usize, 0), a.count()); diff --git a/src/bitflags.zig b/src/bitflags.zig index 90fdbfc737a760..908179686af7b2 100644 --- a/src/bitflags.zig +++ b/src/bitflags.zig @@ -2,11 +2,13 @@ const std = @import("std"); pub fn Bitflags(comptime T: type) type { const tyinfo = @typeInfo(T); - const IntType = tyinfo.Struct.backing_integer.?; + const IntType = tyinfo.@"struct".backing_integer.?; const IntTypeInfo = @typeInfo(IntType); - const IntRepresentingNumOfBits = std.math.IntFittingRange(0, IntTypeInfo.Int.bits); + const IntRepresentingNumOfBits = std.math.IntFittingRange(0, IntTypeInfo.int.bits); return struct { + pub const IMPL_BITFLAGS: u0 = 0; + pub inline fn empty() T { return @bitCast(@as(IntType, 0)); } diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index 648ff54cfdf9c4..b78c9afe7d22ef 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -8,7 +8,6 @@ const String = bun.String; const JSGlobalObject = JSC.JSGlobalObject; const JSValue = JSC.JSValue; const strings = bun.strings; -const is_bindgen = JSC.is_bindgen; const ZigException = JSC.ZigException; const ZigString = JSC.ZigString; const VirtualMachine = JSC.VirtualMachine; @@ -104,10 +103,6 @@ fn messageWithTypeAndLevel_( vals: [*]const JSValue, len: usize, ) bun.JSError!void { - if (comptime is_bindgen) { - return; - } - var console = global.bunVM().console; defer console.default_indent +|= @as(u16, @intFromBool(message_type == .StartGroup)); @@ -2098,7 +2093,7 @@ pub const Formatter = struct { switch (comptime Format) { .StringPossiblyFormatted => { - var str = value.toSlice(this.globalThis, bun.default_allocator); + var str = try value.toSlice(this.globalThis, bun.default_allocator); defer str.deinit(); this.addForNewLine(str.len); const slice = str.slice(); @@ -3438,7 +3433,7 @@ pub const Formatter = struct { ", ... {d} more"; writer.print(comptime Output.prettyFmt(fmt_, enable_ansi_colors), .{ - if (@typeInfo(Number) == .Float) bun.fmt.double(@floatCast(slice[0])) else slice[0], + if (@typeInfo(Number) == .float) bun.fmt.double(@floatCast(slice[0])) else slice[0], }); var leftover = slice[1..]; const max = 512; @@ -3448,7 +3443,7 @@ pub const Formatter = struct { writer.space(); writer.print(comptime Output.prettyFmt(fmt_, enable_ansi_colors), .{ - if (@typeInfo(Number) == .Float) bun.fmt.double(@floatCast(el)) else el, + if (@typeInfo(Number) == .float) bun.fmt.double(@floatCast(el)) else el, }); } @@ -3691,17 +3686,17 @@ pub fn screenshot( ) callconv(JSC.conv) void {} comptime { - @export(messageWithTypeAndLevel, .{ .name = shim.symbolName("messageWithTypeAndLevel") }); - @export(count, .{ .name = shim.symbolName("count") }); - @export(countReset, .{ .name = shim.symbolName("countReset") }); - @export(time, .{ .name = shim.symbolName("time") }); - @export(timeLog, .{ .name = shim.symbolName("timeLog") }); - @export(timeEnd, .{ .name = shim.symbolName("timeEnd") }); - @export(profile, .{ .name = shim.symbolName("profile") }); - @export(profileEnd, .{ .name = shim.symbolName("profileEnd") }); - @export(takeHeapSnapshot, .{ .name = shim.symbolName("takeHeapSnapshot") }); - @export(timeStamp, .{ .name = shim.symbolName("timeStamp") }); - @export(record, .{ .name = shim.symbolName("record") }); - @export(recordEnd, .{ .name = shim.symbolName("recordEnd") }); - @export(screenshot, .{ .name = shim.symbolName("screenshot") }); + @export(&messageWithTypeAndLevel, .{ .name = shim.symbolName("messageWithTypeAndLevel") }); + @export(&count, .{ .name = shim.symbolName("count") }); + @export(&countReset, .{ .name = shim.symbolName("countReset") }); + @export(&time, .{ .name = shim.symbolName("time") }); + @export(&timeLog, .{ .name = shim.symbolName("timeLog") }); + @export(&timeEnd, .{ .name = shim.symbolName("timeEnd") }); + @export(&profile, .{ .name = shim.symbolName("profile") }); + @export(&profileEnd, .{ .name = shim.symbolName("profileEnd") }); + @export(&takeHeapSnapshot, .{ .name = shim.symbolName("takeHeapSnapshot") }); + @export(&timeStamp, .{ .name = shim.symbolName("timeStamp") }); + @export(&record, .{ .name = shim.symbolName("record") }); + @export(&recordEnd, .{ .name = shim.symbolName("recordEnd") }); + @export(&screenshot, .{ .name = shim.symbolName("screenshot") }); } diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 21531ae39b515d..e51a3535f174f0 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -99,75 +99,71 @@ pub const BunObject = struct { @compileError("Must be comptime"); } - if (JSC.is_bindgen) { - return; - } - // --- Getters --- - @export(BunObject.CryptoHasher, .{ .name = getterName("CryptoHasher") }); - @export(BunObject.FFI, .{ .name = getterName("FFI") }); - @export(BunObject.FileSystemRouter, .{ .name = getterName("FileSystemRouter") }); - @export(BunObject.MD4, .{ .name = getterName("MD4") }); - @export(BunObject.MD5, .{ .name = getterName("MD5") }); - @export(BunObject.SHA1, .{ .name = getterName("SHA1") }); - @export(BunObject.SHA224, .{ .name = getterName("SHA224") }); - @export(BunObject.SHA256, .{ .name = getterName("SHA256") }); - @export(BunObject.SHA384, .{ .name = getterName("SHA384") }); - @export(BunObject.SHA512, .{ .name = getterName("SHA512") }); - @export(BunObject.SHA512_256, .{ .name = getterName("SHA512_256") }); - - @export(BunObject.TOML, .{ .name = getterName("TOML") }); - @export(BunObject.Glob, .{ .name = getterName("Glob") }); - @export(BunObject.Transpiler, .{ .name = getterName("Transpiler") }); - @export(BunObject.argv, .{ .name = getterName("argv") }); - @export(BunObject.cwd, .{ .name = getterName("cwd") }); - @export(BunObject.enableANSIColors, .{ .name = getterName("enableANSIColors") }); - @export(BunObject.hash, .{ .name = getterName("hash") }); - @export(BunObject.inspect, .{ .name = getterName("inspect") }); - @export(BunObject.main, .{ .name = getterName("main") }); - @export(BunObject.origin, .{ .name = getterName("origin") }); - @export(BunObject.stderr, .{ .name = getterName("stderr") }); - @export(BunObject.stdin, .{ .name = getterName("stdin") }); - @export(BunObject.stdout, .{ .name = getterName("stdout") }); - @export(BunObject.unsafe, .{ .name = getterName("unsafe") }); - @export(BunObject.semver, .{ .name = getterName("semver") }); - @export(BunObject.embeddedFiles, .{ .name = getterName("embeddedFiles") }); - @export(BunObject.S3Client, .{ .name = getterName("S3Client") }); - @export(BunObject.s3, .{ .name = getterName("s3") }); + @export(&BunObject.CryptoHasher, .{ .name = getterName("CryptoHasher") }); + @export(&BunObject.FFI, .{ .name = getterName("FFI") }); + @export(&BunObject.FileSystemRouter, .{ .name = getterName("FileSystemRouter") }); + @export(&BunObject.MD4, .{ .name = getterName("MD4") }); + @export(&BunObject.MD5, .{ .name = getterName("MD5") }); + @export(&BunObject.SHA1, .{ .name = getterName("SHA1") }); + @export(&BunObject.SHA224, .{ .name = getterName("SHA224") }); + @export(&BunObject.SHA256, .{ .name = getterName("SHA256") }); + @export(&BunObject.SHA384, .{ .name = getterName("SHA384") }); + @export(&BunObject.SHA512, .{ .name = getterName("SHA512") }); + @export(&BunObject.SHA512_256, .{ .name = getterName("SHA512_256") }); + + @export(&BunObject.TOML, .{ .name = getterName("TOML") }); + @export(&BunObject.Glob, .{ .name = getterName("Glob") }); + @export(&BunObject.Transpiler, .{ .name = getterName("Transpiler") }); + @export(&BunObject.argv, .{ .name = getterName("argv") }); + @export(&BunObject.cwd, .{ .name = getterName("cwd") }); + @export(&BunObject.enableANSIColors, .{ .name = getterName("enableANSIColors") }); + @export(&BunObject.hash, .{ .name = getterName("hash") }); + @export(&BunObject.inspect, .{ .name = getterName("inspect") }); + @export(&BunObject.main, .{ .name = getterName("main") }); + @export(&BunObject.origin, .{ .name = getterName("origin") }); + @export(&BunObject.stderr, .{ .name = getterName("stderr") }); + @export(&BunObject.stdin, .{ .name = getterName("stdin") }); + @export(&BunObject.stdout, .{ .name = getterName("stdout") }); + @export(&BunObject.unsafe, .{ .name = getterName("unsafe") }); + @export(&BunObject.semver, .{ .name = getterName("semver") }); + @export(&BunObject.embeddedFiles, .{ .name = getterName("embeddedFiles") }); + @export(&BunObject.S3Client, .{ .name = getterName("S3Client") }); + @export(&BunObject.s3, .{ .name = getterName("s3") }); // --- Getters -- // -- Callbacks -- - @export(BunObject.allocUnsafe, .{ .name = callbackName("allocUnsafe") }); - @export(BunObject.build, .{ .name = callbackName("build") }); - @export(BunObject.color, .{ .name = callbackName("color") }); - @export(BunObject.connect, .{ .name = callbackName("connect") }); - @export(BunObject.createParsedShellScript, .{ .name = callbackName("createParsedShellScript") }); - @export(BunObject.createShellInterpreter, .{ .name = callbackName("createShellInterpreter") }); - @export(BunObject.deflateSync, .{ .name = callbackName("deflateSync") }); - @export(BunObject.file, .{ .name = callbackName("file") }); - @export(BunObject.gunzipSync, .{ .name = callbackName("gunzipSync") }); - @export(BunObject.gzipSync, .{ .name = callbackName("gzipSync") }); - @export(BunObject.indexOfLine, .{ .name = callbackName("indexOfLine") }); - @export(BunObject.inflateSync, .{ .name = callbackName("inflateSync") }); - @export(BunObject.jest, .{ .name = callbackName("jest") }); - @export(BunObject.listen, .{ .name = callbackName("listen") }); - @export(BunObject.mmap, .{ .name = callbackName("mmap") }); - @export(BunObject.nanoseconds, .{ .name = callbackName("nanoseconds") }); - @export(BunObject.openInEditor, .{ .name = callbackName("openInEditor") }); - @export(BunObject.registerMacro, .{ .name = callbackName("registerMacro") }); - @export(BunObject.resolve, .{ .name = callbackName("resolve") }); - @export(BunObject.resolveSync, .{ .name = callbackName("resolveSync") }); - @export(BunObject.serve, .{ .name = callbackName("serve") }); - @export(BunObject.sha, .{ .name = callbackName("sha") }); - @export(BunObject.shellEscape, .{ .name = callbackName("shellEscape") }); - @export(BunObject.shrink, .{ .name = callbackName("shrink") }); - @export(BunObject.sleepSync, .{ .name = callbackName("sleepSync") }); - @export(BunObject.spawn, .{ .name = callbackName("spawn") }); - @export(BunObject.spawnSync, .{ .name = callbackName("spawnSync") }); - @export(BunObject.udpSocket, .{ .name = callbackName("udpSocket") }); - @export(BunObject.which, .{ .name = callbackName("which") }); - @export(BunObject.write, .{ .name = callbackName("write") }); + @export(&BunObject.allocUnsafe, .{ .name = callbackName("allocUnsafe") }); + @export(&BunObject.build, .{ .name = callbackName("build") }); + @export(&BunObject.color, .{ .name = callbackName("color") }); + @export(&BunObject.connect, .{ .name = callbackName("connect") }); + @export(&BunObject.createParsedShellScript, .{ .name = callbackName("createParsedShellScript") }); + @export(&BunObject.createShellInterpreter, .{ .name = callbackName("createShellInterpreter") }); + @export(&BunObject.deflateSync, .{ .name = callbackName("deflateSync") }); + @export(&BunObject.file, .{ .name = callbackName("file") }); + @export(&BunObject.gunzipSync, .{ .name = callbackName("gunzipSync") }); + @export(&BunObject.gzipSync, .{ .name = callbackName("gzipSync") }); + @export(&BunObject.indexOfLine, .{ .name = callbackName("indexOfLine") }); + @export(&BunObject.inflateSync, .{ .name = callbackName("inflateSync") }); + @export(&BunObject.jest, .{ .name = callbackName("jest") }); + @export(&BunObject.listen, .{ .name = callbackName("listen") }); + @export(&BunObject.mmap, .{ .name = callbackName("mmap") }); + @export(&BunObject.nanoseconds, .{ .name = callbackName("nanoseconds") }); + @export(&BunObject.openInEditor, .{ .name = callbackName("openInEditor") }); + @export(&BunObject.registerMacro, .{ .name = callbackName("registerMacro") }); + @export(&BunObject.resolve, .{ .name = callbackName("resolve") }); + @export(&BunObject.resolveSync, .{ .name = callbackName("resolveSync") }); + @export(&BunObject.serve, .{ .name = callbackName("serve") }); + @export(&BunObject.sha, .{ .name = callbackName("sha") }); + @export(&BunObject.shellEscape, .{ .name = callbackName("shellEscape") }); + @export(&BunObject.shrink, .{ .name = callbackName("shrink") }); + @export(&BunObject.sleepSync, .{ .name = callbackName("sleepSync") }); + @export(&BunObject.spawn, .{ .name = callbackName("spawn") }); + @export(&BunObject.spawnSync, .{ .name = callbackName("spawnSync") }); + @export(&BunObject.udpSocket, .{ .name = callbackName("udpSocket") }); + @export(&BunObject.which, .{ .name = callbackName("which") }); + @export(&BunObject.write, .{ .name = callbackName("write") }); // -- Callbacks -- } }; @@ -248,11 +244,10 @@ const IOTask = JSC.IOTask; const zlib = @import("../../zlib.zig"); const Which = @import("../../which.zig"); const ErrorableString = JSC.ErrorableString; -const is_bindgen = JSC.is_bindgen; const max_addressable_memory = std.math.maxInt(u56); const glob = @import("../../glob.zig"); const Async = bun.Async; -const SemverObject = @import("../../install/semver.zig").SemverObject; +const SemverObject = bun.Semver.SemverObject; const Braces = @import("../../shell/braces.zig"); const Shell = @import("../../shell/shell.zig"); @@ -368,7 +363,7 @@ pub fn which(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE return JSC.JSValue.jsNull(); } - bin_str = path_arg.toSlice(globalThis, globalThis.bunVM().allocator); + bin_str = try path_arg.toSlice(globalThis, globalThis.bunVM().allocator); if (globalThis.hasException()) { return .zero; } @@ -391,11 +386,11 @@ pub fn which(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE if (arguments.nextEat()) |arg| { if (!arg.isEmptyOrUndefinedOrNull() and arg.isObject()) { if (try arg.get(globalThis, "PATH")) |str_| { - path_str = str_.toSlice(globalThis, globalThis.bunVM().allocator); + path_str = try str_.toSlice(globalThis, globalThis.bunVM().allocator); } if (try arg.get(globalThis, "cwd")) |str_| { - cwd_str = str_.toSlice(globalThis, globalThis.bunVM().allocator); + cwd_str = try str_.toSlice(globalThis, globalThis.bunVM().allocator); } } } @@ -477,8 +472,7 @@ pub fn inspectTable(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) try buffered_writer.flush(); - var out = bun.String.createUTF8(array.slice()); - return out.transferToJS(globalThis); + return bun.String.createUTF8ForJS(globalThis, array.slice()); } pub fn inspect(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { @@ -700,13 +694,13 @@ pub fn openInEditor(globalThis: js.JSContextRef, callframe: *JSC.CallFrame) bun. var column: ?string = null; if (arguments.nextEat()) |file_path_| { - path = file_path_.toSlice(globalThis, arguments.arena.allocator()).slice(); + path = (try file_path_.toSlice(globalThis, arguments.arena.allocator())).slice(); } if (arguments.nextEat()) |opts| { if (!opts.isUndefinedOrNull()) { if (try opts.getTruthy(globalThis, "editor")) |editor_val| { - var sliced = editor_val.toSlice(globalThis, arguments.arena.allocator()); + var sliced = try editor_val.toSlice(globalThis, arguments.arena.allocator()); const prev_name = edit.name; if (!strings.eqlLong(prev_name, sliced.slice(), true)) { @@ -725,11 +719,11 @@ pub fn openInEditor(globalThis: js.JSContextRef, callframe: *JSC.CallFrame) bun. } if (try opts.getTruthy(globalThis, "line")) |line_| { - line = line_.toSlice(globalThis, arguments.arena.allocator()).slice(); + line = (try line_.toSlice(globalThis, arguments.arena.allocator())).slice(); } if (try opts.getTruthy(globalThis, "column")) |column_| { - column = column_.toSlice(globalThis, arguments.arena.allocator()).slice(); + column = (try column_.toSlice(globalThis, arguments.arena.allocator())).slice(); } } } @@ -1412,7 +1406,7 @@ pub const Crypto = struct { } if (!globalThis.hasException()) { - const slice = arguments[4].toSlice(globalThis, bun.default_allocator); + const slice = try arguments[4].toSlice(globalThis, bun.default_allocator); defer slice.deinit(); const name = slice.slice(); return globalThis.ERR_CRYPTO_INVALID_DIGEST("Invalid digest: {s}", .{name}).throw(); @@ -1926,7 +1920,7 @@ pub const Crypto = struct { hash: []const u8, pub fn toErrorInstance(this: Value, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - const error_code = std.fmt.allocPrint(bun.default_allocator, "PASSWORD_{}", .{PascalToUpperUnderscoreCaseFormatter{ .input = @errorName(this.err) }}) catch bun.outOfMemory(); + const error_code = std.fmt.allocPrint(bun.default_allocator, "PASSWORD{}", .{PascalToUpperUnderscoreCaseFormatter{ .input = @errorName(this.err) }}) catch bun.outOfMemory(); defer bun.default_allocator.free(error_code); const instance = globalObject.createErrorInstance("Password hashing failed with error \"{s}\"", .{@errorName(this.err)}); instance.put(globalObject, ZigString.static("code"), JSC.ZigString.init(error_code).toJS(globalObject)); @@ -2863,7 +2857,7 @@ pub const Crypto = struct { return globalThis.throw("Bun.file() is not supported here yet (it needs an async version)", .{}); } - if (comptime @typeInfo(@TypeOf(Hasher.hash)).Fn.params.len == 3) { + if (comptime @typeInfo(@TypeOf(Hasher.hash)).@"fn".params.len == 3) { Hasher.hash(input.slice(), &output_digest_buf, JSC.VirtualMachine.get().rareData().boringEngine()); } else { Hasher.hash(input.slice(), &output_digest_buf); @@ -2883,7 +2877,7 @@ pub const Crypto = struct { output_digest_slice = bytes[0..Hasher.digest]; } - if (comptime @typeInfo(@TypeOf(Hasher.hash)).Fn.params.len == 3) { + if (comptime @typeInfo(@TypeOf(Hasher.hash)).@"fn".params.len == 3) { Hasher.hash(input.slice(), output_digest_slice, JSC.VirtualMachine.get().rareData().boringEngine()); } else { Hasher.hash(input.slice(), output_digest_slice); @@ -3205,10 +3199,8 @@ pub export fn Bun__escapeHTML8(globalObject: *JSC.JSGlobalObject, input_value: J } comptime { - if (!JSC.is_bindgen) { - _ = Bun__escapeHTML8; - _ = Bun__escapeHTML16; - } + _ = Bun__escapeHTML8; + _ = Bun__escapeHTML16; } pub fn allocUnsafe(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { @@ -3234,7 +3226,7 @@ pub fn mmapFile(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun. const path = brk: { if (args.nextEat()) |path| { if (path.isString()) { - const path_str = path.toSlice(globalThis, args.arena.allocator()); + const path_str = try path.toSlice(globalThis, args.arena.allocator()); if (path_str.len > bun.MAX_PATH_BYTES) { return globalThis.throwInvalidArguments("Path too long", .{}); } @@ -3274,7 +3266,7 @@ pub fn mmapFile(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun. if (try opts.get(globalThis, "offset")) |value| { offset = @as(usize, @intCast(value.toInt64())); - offset = std.mem.alignBackwardAnyAlign(offset, std.mem.page_size); + offset = std.mem.alignBackwardAnyAlign(usize, offset, std.mem.page_size); } } @@ -3402,7 +3394,7 @@ const HashObject = struct { input = array_buffer.byteSlice(); }, else => { - input_slice = arg.toSlice(globalThis, bun.default_allocator); + input_slice = try arg.toSlice(globalThis, bun.default_allocator); input = input_slice.slice(); }, } @@ -3537,7 +3529,7 @@ const UnsafeObject = struct { callframe: *JSC.CallFrame, ) bun.JSError!JSC.JSValue { const args = callframe.arguments_old(2).slice(); - if (args.len < 1 or !args[0].isCell() or !args[0].jsType().isTypedArray()) { + if (args.len < 1 or !args[0].isCell() or !args[0].jsType().isTypedArrayOrArrayBuffer()) { return globalThis.throwInvalidArguments("Expected an ArrayBuffer", .{}); } @@ -3589,7 +3581,7 @@ const TOMLObject = struct { return globalThis.throwInvalidArguments("Expected a string to parse", .{}); } - var input_slice = arguments[0].toSlice(globalThis, bun.default_allocator); + var input_slice = try arguments[0].toSlice(globalThis, bun.default_allocator); defer input_slice.deinit(); var source = logger.Source.initPathString("input.toml", input_slice.slice()); const parse_result = TOMLParser.parse(&source, &log, allocator, false) catch { @@ -4303,12 +4295,10 @@ export fn Bun__reportError(globalObject: *JSGlobalObject, err: JSC.JSValue) void } comptime { - if (!is_bindgen) { - _ = Bun__reportError; - _ = EnvironmentVariables.Bun__getEnvCount; - _ = EnvironmentVariables.Bun__getEnvKey; - _ = EnvironmentVariables.Bun__getEnvValue; - } + _ = Bun__reportError; + _ = EnvironmentVariables.Bun__getEnvCount; + _ = EnvironmentVariables.Bun__getEnvKey; + _ = EnvironmentVariables.Bun__getEnvValue; } pub const JSZlib = struct { diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig index a07d9a242d8a47..cf6abc15f8caac 100644 --- a/src/bun.js/api/JSBundler.zig +++ b/src/bun.js/api/JSBundler.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Api = @import("../../api/schema.zig").Api; -const JavaScript = @import("../javascript.zig"); const QueryStringMap = @import("../../url.zig").QueryStringMap; const CombinedScanner = @import("../../url.zig").CombinedScanner; const bun = @import("root").bun; @@ -11,7 +10,6 @@ const WebCore = @import("../webcore/response.zig"); const Transpiler = bun.transpiler; const options = @import("../../options.zig"); const resolve_path = @import("../../resolver/resolve_path.zig"); -const VirtualMachine = JavaScript.VirtualMachine; const ScriptSrcStream = std.io.FixedBufferStream([]u8); const ZigString = JSC.ZigString; const Fs = @import("../../fs.zig"); @@ -60,6 +58,7 @@ pub const JSBundler = struct { rootdir: OwnedString = OwnedString.initEmpty(bun.default_allocator), serve: Serve = .{}, jsx: options.JSX.Pragma = .{}, + force_node_env: options.BundleOptions.ForceNodeEnv = .unspecified, code_splitting: bool = false, minify: Minify = .{}, no_macros: bool = false, @@ -230,7 +229,7 @@ pub const JSBundler = struct { } else if (env == .true or (env.isNumber() and env.asNumber() == 1)) { this.env_behavior = .load_all; } else if (env.isString()) { - const slice = try env.toSlice2(globalThis, bun.default_allocator); + const slice = try env.toSlice(globalThis, bun.default_allocator); defer slice.deinit(); if (strings.eqlComptime(slice.slice(), "inline")) { this.env_behavior = .load_all; diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 16fd9bf5cc2dde..0c0aa5a27ac73c 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Api = @import("../../api/schema.zig").Api; -const JavaScript = @import("../javascript.zig"); const QueryStringMap = @import("../../url.zig").QueryStringMap; const CombinedScanner = @import("../../url.zig").CombinedScanner; const bun = @import("root").bun; @@ -10,7 +9,6 @@ const js = JSC.C; const WebCore = @import("../webcore/response.zig"); const Transpiler = bun.transpiler; const options = @import("../../options.zig"); -const VirtualMachine = JavaScript.VirtualMachine; const ScriptSrcStream = std.io.FixedBufferStream([]u8); const ZigString = JSC.ZigString; const Fs = @import("../../fs.zig"); @@ -454,7 +452,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std allocator, &transpiler.log, logger.Source.initPathString("tsconfig.json", transpiler.tsconfig_buf), - &VirtualMachine.get().transpiler.resolver.caches.json, + &JSC.VirtualMachine.get().transpiler.resolver.caches.json, ) catch null) |parsed_tsconfig| { transpiler.tsconfig = parsed_tsconfig; } @@ -488,7 +486,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std if (out.isEmpty()) break :macros; transpiler.macros_buf = out.toOwnedSlice(allocator) catch bun.outOfMemory(); const source = logger.Source.initPathString("macros.json", transpiler.macros_buf); - const json = (VirtualMachine.get().transpiler.resolver.caches.json.parseJSON( + const json = (JSC.VirtualMachine.get().transpiler.resolver.caches.json.parseJSON( &transpiler.log, source, allocator, @@ -660,7 +658,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std const replacementValue = JSC.JSObject.getIndex(value, globalThis, 1); if (exportReplacementValue(replacementValue, globalThis)) |to_replace| { const replacementKey = JSC.JSObject.getIndex(value, globalThis, 0); - var slice = (try replacementKey.toSlice(globalThis, bun.default_allocator).cloneIfNeeded(bun.default_allocator)); + var slice = (try (try replacementKey.toSlice(globalThis, bun.default_allocator)).cloneIfNeeded(bun.default_allocator)); const replacement_name = slice.slice(); if (!JSLexer.isIdentifier(replacement_name)) { @@ -731,7 +729,7 @@ pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) b allocator, log, transpiler_options.transform, - JavaScript.VirtualMachine.get().transpiler.env, + JSC.VirtualMachine.get().transpiler.env, ) catch |err| { if ((log.warnings + log.errors) > 0) { return globalThis.throwValue(log.toJS(globalThis, allocator, "Failed to create transpiler")); @@ -1022,7 +1020,7 @@ pub fn transformSync( arena.allocator(), code, loader, - if (comptime JSC.is_bindgen) Transpiler.MacroJSValueType.zero else js_ctx_value, + js_ctx_value, ) orelse { if ((this.transpiler.log.warnings + this.transpiler.log.errors) > 0) { return globalThis.throwValue(this.transpiler.log.toJS(globalThis, globalThis.allocator(), "Parse error")); diff --git a/src/bun.js/api/Timer.zig b/src/bun.js/api/Timer.zig index 9b15fe9aae7b7b..dd9382126b7762 100644 --- a/src/bun.js/api/Timer.zig +++ b/src/bun.js/api/Timer.zig @@ -28,6 +28,8 @@ const TimerHeap = heap.Intrusive(EventLoopTimer, void, EventLoopTimer.less); pub const All = struct { last_id: i32 = 1, + lock: bun.Mutex = .{}, + thread_id: std.Thread.Id, timers: TimerHeap = .{ .context = {}, }, @@ -49,7 +51,15 @@ pub const All = struct { } } = .{}, + pub fn init() @This() { + return .{ + .thread_id = std.Thread.getCurrentId(), + }; + } + pub fn insert(this: *All, timer: *EventLoopTimer) void { + this.lock.lock(); + defer this.lock.unlock(); this.timers.insert(timer); timer.state = .ACTIVE; @@ -59,12 +69,36 @@ pub const All = struct { } pub fn remove(this: *All, timer: *EventLoopTimer) void { + this.lock.lock(); + defer this.lock.unlock(); this.timers.remove(timer); timer.state = .CANCELLED; timer.heap = .{}; } + /// Remove the EventLoopTimer if necessary. + pub fn update(this: *All, timer: *EventLoopTimer, time: *const timespec) void { + this.lock.lock(); + defer this.lock.unlock(); + if (timer.state == .ACTIVE) { + this.timers.remove(timer); + } + + timer.state = .ACTIVE; + if (comptime Environment.isDebug) { + if (&timer.next == time) { + @panic("timer.next == time. For threadsafety reasons, time and timer.next must always be a different pointer."); + } + } + timer.next = time.*; + + this.timers.insert(timer); + if (Environment.isWindows) { + this.ensureUVTimer(@alignCast(@fieldParentPtr("timer", this))); + } + } + fn ensureUVTimer(this: *All, vm: *VirtualMachine) void { if (this.uv_timer.data == null) { this.uv_timer.init(vm.uvLoop()); @@ -129,15 +163,28 @@ pub const All = struct { return VirtualMachine.get().timer.last_id; } - pub fn getTimeout(this: *const All, spec: *timespec) bool { + pub fn getTimeout(this: *All, spec: *timespec, vm: *VirtualMachine) bool { if (this.active_timer_count == 0) { return false; } - if (this.timers.peek()) |min| { - const now = timespec.now(); + var now: timespec = undefined; + var has_set_now: bool = false; + while (this.timers.peek()) |min| { + if (!has_set_now) { + now = timespec.now(); + has_set_now = true; + } + switch (now.order(&min.next)) { .gt, .eq => { + // Side-effect: potentially call the StopIfNecessary timer. + if (min.tag == .WTFTimer) { + _ = this.timers.deleteMin(); + _ = min.fire(&now, vm); + continue; + } + spec.* = .{ .nsec = 0, .sec = 0 }; return true; }, @@ -146,6 +193,8 @@ pub const All = struct { return true; }, } + + unreachable; } return false; @@ -159,22 +208,40 @@ pub const All = struct { _ = &Bun__internal_drainTimers; } - pub fn drainTimers(this: *All, vm: *VirtualMachine) void { - if (this.timers.peek() == null) { - return; - } - - const now = ×pec.now(); + // Getting the current time is expensive on certain platforms. + // We don't want to call it when there are no timers. + // And when we do call it, we want to be sure we only call it once. + // and we do NOT want to hold the lock while the timer is running it's code. + // This function has to be thread-safe. + fn next(this: *All, has_set_now: *bool, now: *timespec) ?*EventLoopTimer { + this.lock.lock(); + defer this.lock.unlock(); - while (this.timers.peek()) |t| { - if (t.next.greater(now)) { - break; + if (this.timers.peek()) |timer| { + if (!has_set_now.*) { + now.* = timespec.now(); + has_set_now.* = true; + } + if (timer.next.greater(now)) { + return null; } - assert(this.timers.deleteMin().? == t); + assert(this.timers.deleteMin().? == timer); + return timer; + } + return null; + } + + pub fn drainTimers(this: *All, vm: *VirtualMachine) void { + // Set in next(). + var now: timespec = undefined; + // Split into a separate variable to avoid increasing the size of the timespec type. + var has_set_now: bool = false; + + while (this.next(&has_set_now, &now)) |t| { switch (t.fire( - now, + &now, vm, )) { .disarm => {}, @@ -235,9 +302,7 @@ pub const All = struct { } comptime { - if (!JSC.is_bindgen) { - @export(setImmediate, .{ .name = "Bun__Timer__setImmediate" }); - } + @export(&setImmediate, .{ .name = "Bun__Timer__setImmediate" }); } pub fn setTimeout( @@ -347,13 +412,11 @@ pub const All = struct { }); comptime { - if (!JSC.is_bindgen) { - @export(setTimeout, .{ .name = Export[0].symbol_name }); - @export(setInterval, .{ .name = Export[1].symbol_name }); - @export(clearTimeout, .{ .name = Export[2].symbol_name }); - @export(clearInterval, .{ .name = Export[3].symbol_name }); - @export(getNextID, .{ .name = Export[4].symbol_name }); - } + @export(&setTimeout, .{ .name = Export[0].symbol_name }); + @export(&setInterval, .{ .name = Export[1].symbol_name }); + @export(&clearTimeout, .{ .name = Export[2].symbol_name }); + @export(&clearInterval, .{ .name = Export[3].symbol_name }); + @export(&getNextID, .{ .name = Export[4].symbol_name }); } }; @@ -381,9 +444,9 @@ pub const TimerObject = struct { }, pub usingnamespace JSC.Codegen.JSTimeout; - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); - extern "C" fn Bun__JSTimeout__call(encodedTimeoutValue: JSValue, globalObject: *JSC.JSGlobalObject) void; + extern "c" fn Bun__JSTimeout__call(encodedTimeoutValue: JSValue, globalObject: *JSC.JSGlobalObject) void; pub fn runImmediateTask(this: *TimerObject, vm: *VirtualMachine) void { if (this.has_cleared_timer) { @@ -467,8 +530,7 @@ pub const TimerObject = struct { switch (this.event_loop_timer.state) { .FIRED => { // If we didn't clear the setInterval, reschedule it starting from - this.event_loop_timer.next = time_before_call; - vm.timer.insert(&this.event_loop_timer); + vm.timer.update(&this.event_loop_timer, &time_before_call); if (this.has_js_ref) { this.setEnableKeepingEventLoopAlive(vm, true); @@ -478,10 +540,7 @@ pub const TimerObject = struct { }, .ACTIVE => { // The developer called timer.refresh() synchronously in the callback. - vm.timer.remove(&this.event_loop_timer); - - this.event_loop_timer.next = time_before_call; - vm.timer.insert(&this.event_loop_timer); + vm.timer.update(&this.event_loop_timer, &time_before_call); // Balance out the ref count. // the transition from "FIRED" -> "ACTIVE" caused it to increment. @@ -620,8 +679,7 @@ pub const TimerObject = struct { this.ref(); } - this.event_loop_timer.next = now; - vm.timer.insert(&this.event_loop_timer); + vm.timer.update(&this.event_loop_timer, &now); this.has_cleared_timer = false; if (this.has_js_ref) { @@ -722,7 +780,7 @@ pub const EventLoopTimer = struct { state: State = .PENDING, - tag: Tag = .TimerCallback, + tag: Tag, pub const Tag = if (Environment.isWindows) enum { TimerCallback, @@ -732,6 +790,7 @@ pub const EventLoopTimer = struct { UpgradedDuplex, DNSResolver, WindowsNamedPipe, + WTFTimer, PostgresSQLConnectionTimeout, PostgresSQLConnectionMaxLifetime, @@ -744,6 +803,7 @@ pub const EventLoopTimer = struct { .UpgradedDuplex => uws.UpgradedDuplex, .DNSResolver => DNSResolver, .WindowsNamedPipe => uws.WindowsNamedPipe, + .WTFTimer => WTFTimer, .PostgresSQLConnectionTimeout => JSC.Postgres.PostgresSQLConnection, .PostgresSQLConnectionMaxLifetime => JSC.Postgres.PostgresSQLConnection, }; @@ -754,6 +814,7 @@ pub const EventLoopTimer = struct { TestRunner, StatWatcherScheduler, UpgradedDuplex, + WTFTimer, DNSResolver, PostgresSQLConnectionTimeout, PostgresSQLConnectionMaxLifetime, @@ -765,6 +826,7 @@ pub const EventLoopTimer = struct { .TestRunner => JSC.Jest.TestRunner, .StatWatcherScheduler => StatWatcherScheduler, .UpgradedDuplex => uws.UpgradedDuplex, + .WTFTimer => WTFTimer, .DNSResolver => DNSResolver, .PostgresSQLConnectionTimeout => JSC.Postgres.PostgresSQLConnection, .PostgresSQLConnectionMaxLifetime => JSC.Postgres.PostgresSQLConnection, @@ -824,6 +886,10 @@ pub const EventLoopTimer = struct { .PostgresSQLConnectionMaxLifetime => return @as(*JSC.Postgres.PostgresSQLConnection, @alignCast(@fieldParentPtr("max_lifetime_timer", this))).onMaxLifetimeTimeout(), inline else => |t| { var container: *t.Type() = @alignCast(@fieldParentPtr("event_loop_timer", this)); + if (comptime t.Type() == WTFTimer) { + return container.fire(now, vm); + } + if (comptime t.Type() == TimerObject) { return container.fire(now, vm); } @@ -858,3 +924,134 @@ pub const EventLoopTimer = struct { }; const timespec = bun.timespec; + +/// A timer created by WTF code and invoked by Bun's event loop +pub const WTFTimer = struct { + /// This is WTF::RunLoop::TimerBase from WebKit + const RunLoopTimer = opaque {}; + + vm: *VirtualMachine, + run_loop_timer: *RunLoopTimer, + event_loop_timer: EventLoopTimer, + imminent: *std.atomic.Value(?*WTFTimer), + repeat: bool, + lock: bun.Mutex = .{}, + + pub usingnamespace bun.New(@This()); + + pub fn init(run_loop_timer: *RunLoopTimer, js_vm: *VirtualMachine) *WTFTimer { + const this = WTFTimer.new(.{ + .vm = js_vm, + .imminent = &js_vm.eventLoop().imminent_gc_timer, + .event_loop_timer = .{ + .next = .{ + .sec = std.math.maxInt(i64), + .nsec = 0, + }, + .tag = .WTFTimer, + .state = .CANCELLED, + }, + .run_loop_timer = run_loop_timer, + .repeat = false, + }); + + return this; + } + + pub export fn WTFTimer__runIfImminent(vm: *VirtualMachine) void { + vm.eventLoop().runImminentGCTimer(); + } + + pub fn run(this: *WTFTimer, vm: *VirtualMachine) void { + if (this.event_loop_timer.state == .ACTIVE) { + vm.timer.remove(&this.event_loop_timer); + } + this.runWithoutRemoving(); + } + + inline fn runWithoutRemoving(this: *const WTFTimer) void { + WTFTimer__fire(this.run_loop_timer); + } + + pub fn update(this: *WTFTimer, seconds: f64, repeat: bool) void { + // There's only one of these per VM, and each VM has its own imminent_gc_timer + this.imminent.store(if (seconds == 0) this else null, .seq_cst); + + if (seconds == 0.0) { + return; + } + + const modf = std.math.modf(seconds); + var interval = bun.timespec.now(); + interval.sec += @intFromFloat(modf.ipart); + interval.nsec += @intFromFloat(modf.fpart * std.time.ns_per_s); + if (interval.nsec >= std.time.ns_per_s) { + interval.sec += 1; + interval.nsec -= std.time.ns_per_s; + } + + this.vm.timer.update(&this.event_loop_timer, &interval); + this.repeat = repeat; + } + + pub fn cancel(this: *WTFTimer) void { + this.lock.lock(); + defer this.lock.unlock(); + this.imminent.store(null, .monotonic); + if (this.event_loop_timer.state == .ACTIVE) { + this.vm.timer.remove(&this.event_loop_timer); + } + } + + pub fn fire(this: *WTFTimer, _: *const bun.timespec, _: *VirtualMachine) EventLoopTimer.Arm { + this.event_loop_timer.state = .FIRED; + this.imminent.store(null, .monotonic); + this.runWithoutRemoving(); + return if (this.repeat) + .{ .rearm = this.event_loop_timer.next } + else + .disarm; + } + + pub fn deinit(this: *WTFTimer) void { + this.cancel(); + this.destroy(); + } + + export fn WTFTimer__create(run_loop_timer: *RunLoopTimer) ?*anyopaque { + if (VirtualMachine.is_bundler_thread_for_bytecode_cache) { + return null; + } + + return init(run_loop_timer, VirtualMachine.get()); + } + + export fn WTFTimer__update(this: *WTFTimer, seconds: f64, repeat: bool) void { + this.update(seconds, repeat); + } + + export fn WTFTimer__deinit(this: *WTFTimer) void { + this.deinit(); + } + + export fn WTFTimer__isActive(this: *const WTFTimer) bool { + return this.event_loop_timer.state == .ACTIVE or (this.imminent.load(.monotonic) orelse return false) == this; + } + + export fn WTFTimer__cancel(this: *WTFTimer) void { + this.cancel(); + } + + export fn WTFTimer__secondsUntilTimer(this: *WTFTimer) f64 { + this.lock.lock(); + defer this.lock.unlock(); + if (this.event_loop_timer.state == .ACTIVE) { + const until = this.event_loop_timer.next.duration(&bun.timespec.now()); + const sec: f64, const nsec: f64 = .{ @floatFromInt(until.sec), @floatFromInt(until.nsec) }; + return sec + nsec / std.time.ns_per_s; + } + return std.math.inf(f64); + } + + extern fn WTFTimer__fire(this: *RunLoopTimer) void; +}; diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index 63e74b34e811d9..8c365c2920fb09 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -41,10 +41,7 @@ const LibInfo = struct { if (loaded) return handle; loaded = true; - const RTLD_LAZY = 1; - const RTLD_LOCAL = 4; - - handle = bun.C.dlopen("libinfo.dylib", RTLD_LAZY | RTLD_LOCAL); + handle = bun.C.dlopen("libinfo.dylib", .{ .LAZY = true, .LOCAL = true }); if (handle == null) Output.debug("libinfo.dylib not found", .{}); return handle; @@ -1395,7 +1392,7 @@ pub const InternalDNS = struct { // https://github.com/nodejs/node/issues/33816 // https://github.com/aio-libs/aiohttp/issues/5357 // https://github.com/libuv/libuv/issues/2225 - .flags = if (Environment.isPosix) bun.C.translated.AI_ADDRCONFIG else 0, + .flags = if (Environment.isPosix) .{ .ADDRCONFIG = true } else .{}, .next = null, .protocol = 0, .socktype = std.c.SOCK.STREAM, @@ -1527,7 +1524,7 @@ pub const InternalDNS = struct { if (Environment.isWindows) { const wsa = std.os.windows.ws2_32; const wsa_hints = wsa.addrinfo{ - .flags = 0, + .flags = .{}, .family = wsa.AF.UNSPEC, .socktype = wsa.SOCK.STREAM, .protocol = 0, @@ -1691,7 +1688,7 @@ pub const InternalDNS = struct { defer hostname_slice.deinit(); if (hostname_or_url.isString()) { - hostname_slice = hostname_or_url.toSlice(globalThis, bun.default_allocator); + hostname_slice = try hostname_or_url.toSlice(globalThis, bun.default_allocator); } else { return globalThis.throwInvalidArguments("hostname must be a string", .{}); } @@ -1756,16 +1753,16 @@ pub const InternalDNS = struct { pub const InternalDNSRequest = InternalDNS.Request; comptime { - @export(InternalDNS.us_getaddrinfo_set, .{ + @export(&InternalDNS.us_getaddrinfo_set, .{ .name = "Bun__addrinfo_set", }); - @export(InternalDNS.us_getaddrinfo, .{ + @export(&InternalDNS.us_getaddrinfo, .{ .name = "Bun__addrinfo_get", }); - @export(InternalDNS.freeaddrinfo, .{ + @export(&InternalDNS.freeaddrinfo, .{ .name = "Bun__addrinfo_freeRequest", }); - @export(InternalDNS.getRequestResult, .{ + @export(&InternalDNS.getRequestResult, .{ .name = "Bun__addrinfo_getRequestResult", }); } @@ -1802,7 +1799,7 @@ pub const DNSResolver = struct { pending_nameinfo_cache_cares: NameInfoPendingCache = NameInfoPendingCache.init(), pub usingnamespace JSC.Codegen.JSDNSResolver; - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); const PollsMap = std.AutoArrayHashMap(c_ares.ares_socket_t, *PollType); @@ -1912,7 +1909,7 @@ pub const DNSResolver = struct { } fn anyRequestsPending(this: *DNSResolver) bool { - inline for (@typeInfo(DNSResolver).Struct.fields) |field| { + inline for (@typeInfo(DNSResolver).@"struct".fields) |field| { if (comptime std.mem.startsWith(u8, field.name, "pending_")) { const set = &@field(this, field.name).available; if (set.count() < set.capacity()) { @@ -2522,7 +2519,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolve", "name", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); switch (record_type) { RecordType.A => { @@ -2585,7 +2582,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("reverse", "ip", "non-empty string"); } - const ip_slice = ip_str.toSliceClone(globalThis, bun.default_allocator); + const ip_slice = try ip_str.toSliceClone(globalThis, bun.default_allocator); const ip = ip_slice.slice(); const channel: *c_ares.Channel = switch (this.getChannel()) { .result => |res| res, @@ -2721,7 +2718,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveSrv", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_ares_srv_reply, "srv", name.slice(), globalThis); } @@ -2747,7 +2744,7 @@ pub const DNSResolver = struct { return .zero; }; - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_ares_soa_reply, "soa", name.slice(), globalThis); } @@ -2777,7 +2774,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveCaa", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_ares_caa_reply, "caa", name.slice(), globalThis); } @@ -2803,7 +2800,7 @@ pub const DNSResolver = struct { return .zero; }; - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_hostent, "ns", name.slice(), globalThis); } @@ -2833,7 +2830,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolvePtr", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_hostent, "ptr", name.slice(), globalThis); } @@ -2863,7 +2860,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveCname", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_hostent, "cname", name.slice(), globalThis); } @@ -2893,7 +2890,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveMx", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_ares_mx_reply, "mx", name.slice(), globalThis); } @@ -2923,7 +2920,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveNaptr", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_ares_naptr_reply, "naptr", name.slice(), globalThis); } @@ -2953,7 +2950,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveTxt", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_ares_txt_reply, "txt", name.slice(), globalThis); } @@ -2983,7 +2980,7 @@ pub const DNSResolver = struct { return globalThis.throwInvalidArgumentType("resolveAny", "hostname", "non-empty string"); } - const name = name_str.toSliceClone(globalThis, bun.default_allocator); + const name = try name_str.toSliceClone(globalThis, bun.default_allocator); return this.doResolveCAres(c_ares.struct_any_reply, "any", name.slice(), globalThis); } @@ -3396,40 +3393,40 @@ pub const DNSResolver = struct { comptime { const js_resolve = JSC.toJSHostFunction(globalResolve); - @export(js_resolve, .{ .name = "Bun__DNS__resolve" }); + @export(&js_resolve, .{ .name = "Bun__DNS__resolve" }); const js_lookup = JSC.toJSHostFunction(globalLookup); - @export(js_lookup, .{ .name = "Bun__DNS__lookup" }); + @export(&js_lookup, .{ .name = "Bun__DNS__lookup" }); const js_resolveTxt = JSC.toJSHostFunction(globalResolveTxt); - @export(js_resolveTxt, .{ .name = "Bun__DNS__resolveTxt" }); + @export(&js_resolveTxt, .{ .name = "Bun__DNS__resolveTxt" }); const js_resolveSoa = JSC.toJSHostFunction(globalResolveSoa); - @export(js_resolveSoa, .{ .name = "Bun__DNS__resolveSoa" }); + @export(&js_resolveSoa, .{ .name = "Bun__DNS__resolveSoa" }); const js_resolveMx = JSC.toJSHostFunction(globalResolveMx); - @export(js_resolveMx, .{ .name = "Bun__DNS__resolveMx" }); + @export(&js_resolveMx, .{ .name = "Bun__DNS__resolveMx" }); const js_resolveNaptr = JSC.toJSHostFunction(globalResolveNaptr); - @export(js_resolveNaptr, .{ .name = "Bun__DNS__resolveNaptr" }); + @export(&js_resolveNaptr, .{ .name = "Bun__DNS__resolveNaptr" }); const js_resolveSrv = JSC.toJSHostFunction(globalResolveSrv); - @export(js_resolveSrv, .{ .name = "Bun__DNS__resolveSrv" }); + @export(&js_resolveSrv, .{ .name = "Bun__DNS__resolveSrv" }); const js_resolveCaa = JSC.toJSHostFunction(globalResolveCaa); - @export(js_resolveCaa, .{ .name = "Bun__DNS__resolveCaa" }); + @export(&js_resolveCaa, .{ .name = "Bun__DNS__resolveCaa" }); const js_resolveNs = JSC.toJSHostFunction(globalResolveNs); - @export(js_resolveNs, .{ .name = "Bun__DNS__resolveNs" }); + @export(&js_resolveNs, .{ .name = "Bun__DNS__resolveNs" }); const js_resolvePtr = JSC.toJSHostFunction(globalResolvePtr); - @export(js_resolvePtr, .{ .name = "Bun__DNS__resolvePtr" }); + @export(&js_resolvePtr, .{ .name = "Bun__DNS__resolvePtr" }); const js_resolveCname = JSC.toJSHostFunction(globalResolveCname); - @export(js_resolveCname, .{ .name = "Bun__DNS__resolveCname" }); + @export(&js_resolveCname, .{ .name = "Bun__DNS__resolveCname" }); const js_resolveAny = JSC.toJSHostFunction(globalResolveAny); - @export(js_resolveAny, .{ .name = "Bun__DNS__resolveAny" }); + @export(&js_resolveAny, .{ .name = "Bun__DNS__resolveAny" }); const js_getGlobalServers = JSC.toJSHostFunction(getGlobalServers); - @export(js_getGlobalServers, .{ .name = "Bun__DNS__getServers" }); + @export(&js_getGlobalServers, .{ .name = "Bun__DNS__getServers" }); const js_setGlobalServers = JSC.toJSHostFunction(setGlobalServers); - @export(js_setGlobalServers, .{ .name = "Bun__DNS__setServers" }); + @export(&js_setGlobalServers, .{ .name = "Bun__DNS__setServers" }); const js_reverse = JSC.toJSHostFunction(globalReverse); - @export(js_reverse, .{ .name = "Bun__DNS__reverse" }); + @export(&js_reverse, .{ .name = "Bun__DNS__reverse" }); const js_lookupService = JSC.toJSHostFunction(globalLookupService); - @export(js_lookupService, .{ .name = "Bun__DNS__lookupService" }); + @export(&js_lookupService, .{ .name = "Bun__DNS__lookupService" }); const js_prefetchFromJS = JSC.toJSHostFunction(InternalDNS.prefetchFromJS); - @export(js_prefetchFromJS, .{ .name = "Bun__DNS__prefetch" }); + @export(&js_prefetchFromJS, .{ .name = "Bun__DNS__prefetch" }); const js_getDNSCacheStats = JSC.toJSHostFunction(InternalDNS.getDNSCacheStats); - @export(js_getDNSCacheStats, .{ .name = "Bun__DNS__getCacheStats" }); + @export(&js_getDNSCacheStats, .{ .name = "Bun__DNS__getCacheStats" }); } }; diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index 7696d010b2e8e1..87b719740cf123 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -530,7 +530,7 @@ const Handlers = struct { globalObject: *JSC.JSGlobalObject, strong_ctx: JSC.Strong = .{}, - pub fn callEventHandler(this: *Handlers, comptime event: @Type(.EnumLiteral), thisValue: JSValue, data: []const JSValue) bool { + 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; @@ -546,7 +546,7 @@ const Handlers = struct { return true; } - pub fn callEventHandlerWithResult(this: *Handlers, comptime event: @Type(.EnumLiteral), thisValue: JSValue, data: []const JSValue) JSValue { + 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; @@ -643,8 +643,7 @@ const Handlers = struct { pub const H2FrameParser = struct { pub const log = Output.scoped(.H2FrameParser, false); pub usingnamespace JSC.Codegen.JSH2FrameParser; - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); - pub const DEBUG_REFCOUNT_NAME = "H2"; + pub usingnamespace bun.NewRefCounted(@This(), deinit, "H2"); const ENABLE_AUTO_CORK = true; // ENABLE CORK OPTIMIZATION const ENABLE_ALLOCATOR_POOL = true; // ENABLE HIVE ALLOCATOR OPTIMIZATION @@ -1104,7 +1103,10 @@ pub const H2FrameParser = struct { this.signal = null; signal.deinit(); } - JSC.VirtualMachine.get().eventLoop().processGCTimer(); + // unsafe to ask GC to run if we are already inside GC + if (!finalizing) { + JSC.VirtualMachine.get().eventLoop().processGCTimer(); + } } }; @@ -1353,7 +1355,7 @@ pub const H2FrameParser = struct { _ = this.write(&buffer); } - pub fn dispatch(this: *H2FrameParser, comptime event: @Type(.EnumLiteral), value: JSC.JSValue) void { + pub fn dispatch(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: JSC.JSValue) void { JSC.markBinding(@src()); const ctx_value = this.strong_ctx.get() orelse return; @@ -1361,7 +1363,7 @@ pub const H2FrameParser = struct { _ = this.handlers.callEventHandler(event, ctx_value, &[_]JSC.JSValue{ ctx_value, value }); } - pub fn call(this: *H2FrameParser, comptime event: @Type(.EnumLiteral), value: JSC.JSValue) JSValue { + pub fn call(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: JSC.JSValue) JSValue { JSC.markBinding(@src()); const ctx_value = this.strong_ctx.get() orelse return .zero; @@ -1373,7 +1375,7 @@ pub const H2FrameParser = struct { _ = this.handlers.callWriteCallback(callback, &[_]JSC.JSValue{}); } - pub fn dispatchWithExtra(this: *H2FrameParser, comptime event: @Type(.EnumLiteral), value: JSC.JSValue, extra: JSC.JSValue) void { + pub fn dispatchWithExtra(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: JSC.JSValue, extra: JSC.JSValue) void { JSC.markBinding(@src()); const ctx_value = this.strong_ctx.get() orelse return; @@ -1382,7 +1384,7 @@ pub const H2FrameParser = struct { _ = this.handlers.callEventHandler(event, ctx_value, &[_]JSC.JSValue{ ctx_value, value, extra }); } - pub fn dispatchWith2Extra(this: *H2FrameParser, comptime event: @Type(.EnumLiteral), value: JSC.JSValue, extra: JSC.JSValue, extra2: JSC.JSValue) void { + pub fn dispatchWith2Extra(this: *H2FrameParser, comptime event: @Type(.enum_literal), value: JSC.JSValue, extra: JSC.JSValue, extra2: JSC.JSValue) void { JSC.markBinding(@src()); const ctx_value = this.strong_ctx.get() orelse return; @@ -1391,7 +1393,7 @@ pub const H2FrameParser = struct { extra2.ensureStillAlive(); _ = this.handlers.callEventHandler(event, ctx_value, &[_]JSC.JSValue{ ctx_value, value, extra, extra2 }); } - pub fn dispatchWith3Extra(this: *H2FrameParser, comptime event: @Type(.EnumLiteral), value: JSC.JSValue, extra: JSC.JSValue, extra2: JSC.JSValue, extra3: JSC.JSValue) void { + pub fn dispatchWith3Extra(this: *H2FrameParser, comptime event: @Type(.enum_literal), 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; diff --git a/src/bun.js/api/bun/process.zig b/src/bun.js/api/bun/process.zig index d7e7c5be142151..b6fed57c8a502d 100644 --- a/src/bun.js/api/bun/process.zig +++ b/src/bun.js/api/bun/process.zig @@ -11,12 +11,12 @@ const Maybe = JSC.Maybe; const win_rusage = struct { utime: struct { - tv_sec: i64 = 0, - tv_usec: i64 = 0, + sec: i64 = 0, + usec: i64 = 0, }, stime: struct { - tv_sec: i64 = 0, - tv_usec: i64 = 0, + sec: i64 = 0, + usec: i64 = 0, }, maxrss: u64 = 0, ixrss: u0 = 0, @@ -54,16 +54,16 @@ pub fn uv_getrusage(process: *uv.uv_process_t) win_rusage { var kerneltime: WinTime = undefined; var usertime: WinTime = undefined; // We at least get process times - if (std.os.windows.kernel32.GetProcessTimes(process_pid, &starttime, &exittime, &kerneltime, &usertime) == 1) { + if (bun.windows.GetProcessTimes(process_pid, &starttime, &exittime, &kerneltime, &usertime) == 1) { var temp: u64 = (@as(u64, kerneltime.dwHighDateTime) << 32) | kerneltime.dwLowDateTime; if (temp > 0) { - usage_info.stime.tv_sec = @intCast(temp / 10000000); - usage_info.stime.tv_usec = @intCast(temp % 1000000); + usage_info.stime.sec = @intCast(temp / 10000000); + usage_info.stime.usec = @intCast(temp % 1000000); } temp = (@as(u64, usertime.dwHighDateTime) << 32) | usertime.dwLowDateTime; if (temp > 0) { - usage_info.utime.tv_sec = @intCast(temp / 10000000); - usage_info.utime.tv_usec = @intCast(temp % 1000000); + usage_info.utime.sec = @intCast(temp / 10000000); + usage_info.utime.usec = @intCast(temp % 1000000); } } var counters: IO_COUNTERS = .{}; @@ -110,23 +110,23 @@ pub const ProcessExitHandler = struct { } switch (this.ptr.tag()) { - .Subprocess => { + @field(TaggedPointer.Tag, @typeName(Subprocess)) => { const subprocess = this.ptr.as(Subprocess); subprocess.onProcessExit(process, status, rusage); }, - .LifecycleScriptSubprocess => { + @field(TaggedPointer.Tag, @typeName(LifecycleScriptSubprocess)) => { const subprocess = this.ptr.as(LifecycleScriptSubprocess); subprocess.onProcessExit(process, status, rusage); }, - .ProcessHandle => { + @field(TaggedPointer.Tag, @typeName(ProcessHandle)) => { const subprocess = this.ptr.as(ProcessHandle); subprocess.onProcessExit(process, status, rusage); }, - @field(TaggedPointer.Tag, bun.meta.typeBaseName(@typeName(ShellSubprocess))) => { + @field(TaggedPointer.Tag, @typeName(ShellSubprocess)) => { const subprocess = this.ptr.as(ShellSubprocess); subprocess.onProcessExit(process, status, rusage); }, - @field(TaggedPointer.Tag, bun.meta.typeBaseName(@typeName(SyncProcess))) => { + @field(TaggedPointer.Tag, @typeName(SyncProcess)) => { const subprocess = this.ptr.as(SyncProcess); if (comptime Environment.isPosix) { @panic("This code should not reached"); @@ -157,7 +157,7 @@ pub const Process = struct { return @sizeOf(@This()); } - pub usingnamespace bun.NewRefCounted(Process, deinit); + pub usingnamespace bun.NewRefCounted(Process, deinit, null); pub fn setExitHandler(this: *Process, handler: anytype) void { this.exit_handler.init(handler); @@ -924,7 +924,7 @@ const WaiterThreadPosix = struct { .mask = current_mask, .flags = std.posix.SA.NOCLDSTOP, }; - std.posix.sigaction(std.posix.SIG.CHLD, &act, null) catch {}; + std.posix.sigaction(std.posix.SIG.CHLD, &act, null); } } @@ -2018,7 +2018,9 @@ pub const sync = struct { pub fn spawn( options: *const Options, ) !Maybe(Result) { - const envp = options.envp orelse std.c.environ; + // [*:null]?[*:0]const u8 + // [*:null]?[*:0]u8 + const envp = options.envp orelse @as([*:null]?[*:0]const u8, @ptrCast(std.c.environ)); const argv = options.argv; var string_builder = bun.StringBuilder{}; defer string_builder.deinit(bun.default_allocator); @@ -2040,16 +2042,16 @@ pub const sync = struct { } // Forward signals from parent to the child process. - extern "C" fn Bun__registerSignalsForForwarding() void; - extern "C" fn Bun__unregisterSignalsForForwarding() void; + extern "c" fn Bun__registerSignalsForForwarding() void; + extern "c" fn Bun__unregisterSignalsForForwarding() void; // The PID to forward signals to. // Set to 0 when unregistering. - extern "C" var Bun__currentSyncPID: i64; + extern "c" var Bun__currentSyncPID: i64; // Race condition: a signal could be sent before spawnProcessPosix returns. // We need to make sure to send it after the process is spawned. - extern "C" fn Bun__sendPendingSignalIfNecessary() void; + extern "c" fn Bun__sendPendingSignalIfNecessary() void; fn spawnPosix( options: *const Options, diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 5b35669156203e..93801a0e809ab1 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -614,7 +614,13 @@ pub const Listener = struct { const ssl_enabled = ssl != null; - var socket_flags: i32 = if (exclusive) uws.LIBUS_LISTEN_EXCLUSIVE_PORT else (if (socket_config.reusePort) uws.LIBUS_SOCKET_REUSE_PORT else uws.LIBUS_LISTEN_DEFAULT); + var socket_flags: i32 = if (exclusive) + uws.LIBUS_LISTEN_EXCLUSIVE_PORT + else if (socket_config.reusePort) + uws.LIBUS_LISTEN_REUSE_PORT | uws.LIBUS_LISTEN_REUSE_ADDR + else + uws.LIBUS_LISTEN_DEFAULT; + if (socket_config.allowHalfOpen) { socket_flags |= uws.LIBUS_SOCKET_ALLOW_HALF_OPEN; } @@ -906,7 +912,7 @@ pub const Listener = struct { if (!hostname.isString()) { return global.throwInvalidArguments("hostname pattern expects a string", .{}); } - const host_str = hostname.toSlice( + const host_str = try hostname.toSlice( global, bun.default_allocator, ); @@ -1336,9 +1342,7 @@ fn NewSocket(comptime ssl: bool) type { // This is wasteful because it means we are keeping a JSC::Weak for every single open socket has_pending_activity: std.atomic.Value(bool) = std.atomic.Value(bool).init(true), native_callback: NativeCallbacks = .none, - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); - - pub const DEBUG_REFCOUNT_NAME = "Socket"; + pub usingnamespace bun.NewRefCounted(@This(), deinit, "Socket"); // We use this direct callbacks on HTTP2 when available pub const NativeCallbacks = union(enum) { @@ -1389,8 +1393,6 @@ fn NewSocket(comptime ssl: bool) type { JSC.Codegen.JSTLSSocket; pub fn hasPendingActivity(this: *This) callconv(.C) bool { - @fence(.acquire); - return this.has_pending_activity.load(.acquire); } @@ -3877,9 +3879,9 @@ pub const WindowsNamedPipeListeningContext = if (Environment.isWindows) struct { BoringSSL.load(); const ctx_opts: uws.us_bun_socket_context_options_t = JSC.API.ServerConfig.SSLConfig.asUSockets(ssl_options); + var err: uws.create_bun_socket_error_t = .none; // Create SSL context using uSockets to match behavior of node.js - const ctx = uws.create_ssl_context_from_bun_options(ctx_opts) orelse return error.InvalidOptions; // invalid options - errdefer BoringSSL.SSL_CTX_free(ctx); + const ctx = uws.create_ssl_context_from_bun_options(ctx_opts, &err) orelse return error.InvalidOptions; // invalid options this.ctx = ctx; } @@ -4372,6 +4374,9 @@ pub fn jsCreateSocketPair(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JS return global.throwValue(err.toJSC(global)); } + _ = bun.sys.setNonblocking(bun.toFD(fds_[0])); + _ = bun.sys.setNonblocking(bun.toFD(fds_[1])); + const array = JSC.JSValue.createEmptyArray(global, 2); array.putIndex(global, 0, JSC.jsNumber(fds_[0])); array.putIndex(global, 1, JSC.jsNumber(fds_[1])); diff --git a/src/bun.js/api/bun/ssl_wrapper.zig b/src/bun.js/api/bun/ssl_wrapper.zig index c75fba25fa56a1..7a8a74378fac46 100644 --- a/src/bun.js/api/bun/ssl_wrapper.zig +++ b/src/bun.js/api/bun/ssl_wrapper.zig @@ -97,8 +97,9 @@ pub fn SSLWrapper(comptime T: type) type { BoringSSL.load(); const ctx_opts: uws.us_bun_socket_context_options_t = JSC.API.ServerConfig.SSLConfig.asUSockets(ssl_options); + var err: uws.create_bun_socket_error_t = .none; // Create SSL context using uSockets to match behavior of node.js - const ctx = uws.create_ssl_context_from_bun_options(ctx_opts) orelse return error.InvalidOptions; // invalid options + const ctx = uws.create_ssl_context_from_bun_options(ctx_opts, &err) orelse return error.InvalidOptions; // invalid options errdefer BoringSSL.SSL_CTX_free(ctx); return try This.initWithCTX(ctx, is_client, handlers); } diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index a0192a0f1d7d46..5a30592c49fc07 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -48,8 +48,8 @@ pub const ResourceUsage = struct { var cpu = JSC.JSValue.createEmptyObjectWithNullPrototype(globalObject); const rusage = this.rusage; - const usrTime = JSValue.fromTimevalNoTruncate(globalObject, rusage.utime.tv_usec, rusage.utime.tv_sec); - const sysTime = JSValue.fromTimevalNoTruncate(globalObject, rusage.stime.tv_usec, rusage.stime.tv_sec); + const usrTime = JSValue.fromTimevalNoTruncate(globalObject, rusage.utime.usec, rusage.utime.sec); + const sysTime = JSValue.fromTimevalNoTruncate(globalObject, rusage.stime.usec, rusage.stime.sec); cpu.put(globalObject, JSC.ZigString.static("user"), usrTime); cpu.put(globalObject, JSC.ZigString.static("system"), sysTime); @@ -199,7 +199,7 @@ pub const Subprocess = struct { ref_count: u32 = 1, abort_signal: ?*JSC.AbortSignal = null, - usingnamespace bun.NewRefCounted(@This(), Subprocess.deinit); + usingnamespace bun.NewRefCounted(@This(), deinit, null); pub const Flags = packed struct { is_sync: bool = false, @@ -279,7 +279,6 @@ pub const Subprocess = struct { } pub fn updateHasPendingActivity(this: *Subprocess) void { - @fence(.seq_cst); if (comptime Environment.isDebug) { log("updateHasPendingActivity() {any} -> {any}", .{ this.has_pending_activity.raw, @@ -342,7 +341,6 @@ pub const Subprocess = struct { } pub fn hasPendingActivity(this: *Subprocess) callconv(.C) bool { - @fence(.acquire); return this.has_pending_activity.load(.acquire); } @@ -684,7 +682,7 @@ pub const Subprocess = struct { return this.process.kill(@intCast(sig)); } - fn hasCalledGetter(this: *Subprocess, comptime getter: @Type(.EnumLiteral)) bool { + fn hasCalledGetter(this: *Subprocess, comptime getter: @Type(.enum_literal)) bool { return this.observable_getters.contains(getter); } @@ -853,7 +851,7 @@ pub const Subprocess = struct { ref_count: u32 = 1, buffer: []const u8 = "", - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); + pub usingnamespace bun.NewRefCounted(@This(), _deinit, null); const This = @This(); const print = bun.Output.scoped(.StaticPipeWriter, false); @@ -940,7 +938,7 @@ pub const Subprocess = struct { this.process.onCloseIO(.stdin); } - pub fn deinit(this: *This) void { + fn _deinit(this: *This) void { this.writer.end(); this.source.detach(); this.destroy(); @@ -981,7 +979,7 @@ pub const Subprocess = struct { pub const IOReader = bun.io.BufferedReader; pub const Poll = IOReader; - pub usingnamespace bun.NewRefCounted(PipeReader, PipeReader.deinit); + pub usingnamespace bun.NewRefCounted(PipeReader, _deinit, null); pub fn memoryCost(this: *const PipeReader) usize { return this.reader.memoryCost(); @@ -1148,7 +1146,7 @@ pub const Subprocess = struct { return this.event_loop.virtual_machine.uwsLoop(); } - fn deinit(this: *PipeReader) void { + fn _deinit(this: *PipeReader) void { if (comptime Environment.isPosix) { bun.assert(this.reader.isDone()); } @@ -1570,7 +1568,7 @@ pub const Subprocess = struct { } } - fn closeIO(this: *Subprocess, comptime io: @Type(.EnumLiteral)) void { + fn closeIO(this: *Subprocess, comptime io: @Type(.enum_literal)) void { if (this.closed.contains(io)) return; this.closed.insert(io); @@ -2388,21 +2386,29 @@ pub const Subprocess = struct { jsc_vm.onSubprocessSpawn(subprocess.process); } - while (subprocess.hasPendingActivityNonThreadsafe()) { - if (subprocess.stdin == .buffer) { - subprocess.stdin.buffer.watch(); - } + // We cannot release heap access while JS is running + { + const old_vm = jsc_vm.uwsLoop().internal_loop_data.jsc_vm; + jsc_vm.uwsLoop().internal_loop_data.jsc_vm = null; + defer { + jsc_vm.uwsLoop().internal_loop_data.jsc_vm = old_vm; + } + while (subprocess.hasPendingActivityNonThreadsafe()) { + if (subprocess.stdin == .buffer) { + subprocess.stdin.buffer.watch(); + } - if (subprocess.stderr == .pipe) { - subprocess.stderr.pipe.watch(); - } + if (subprocess.stderr == .pipe) { + subprocess.stderr.pipe.watch(); + } - if (subprocess.stdout == .pipe) { - subprocess.stdout.pipe.watch(); - } + if (subprocess.stdout == .pipe) { + subprocess.stdout.pipe.watch(); + } - jsc_vm.tick(); - jsc_vm.eventLoop().autoTick(); + jsc_vm.tick(); + jsc_vm.eventLoop().autoTick(); + } } subprocess.updateHasPendingActivity(); diff --git a/src/bun.js/api/bun/udp_socket.zig b/src/bun.js/api/bun/udp_socket.zig index 4786b5228fe064..e29508f3a05275 100644 --- a/src/bun.js/api/bun/udp_socket.zig +++ b/src/bun.js/api/bun/udp_socket.zig @@ -282,7 +282,7 @@ pub const UDPSocket = struct { globalThis: *JSGlobalObject, thisValue: JSValue = .zero, - ref: JSC.Ref = JSC.Ref.init(), + jsc_ref: JSC.Ref = JSC.Ref.init(), poll_ref: Async.KeepAlive = Async.KeepAlive.init(), // if marked as closed the socket pointer may be stale closed: bool = false, @@ -864,8 +864,7 @@ pub const UDPSocket = struct { }; const slice = bun.fmt.formatIp(address, &text_buf) catch unreachable; - var str = bun.String.createLatin1(slice); - return str.transferToJS(globalThis); + return bun.String.createUTF8ForJS(globalThis, slice); } pub fn getAddress(this: *This, globalThis: *JSGlobalObject) JSValue { diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index 3f21d30948b228..6c23fcc0aa1a5e 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -81,8 +81,8 @@ const Offsets = extern struct { JSArrayBufferView__offsetOfVector: u32, JSCell__offsetOfType: u32, - extern "C" var Bun__FFI__offsets: Offsets; - extern "C" fn Bun__FFI__ensureOffsetsAreLoaded() void; + extern "c" var Bun__FFI__offsets: Offsets; + extern "c" fn Bun__FFI__ensureOffsetsAreLoaded() void; fn loadOnce() void { Bun__FFI__ensureOffsetsAreLoaded(); } @@ -165,27 +165,27 @@ pub const FFI = struct { }; const stdarg = struct { - extern "C" fn ffi_vfprintf(*anyopaque, [*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_vprintf([*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_fprintf(*anyopaque, [*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_printf([*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_fscanf(*anyopaque, [*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_scanf([*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_sscanf([*:0]const u8, [*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_vsscanf([*:0]const u8, [*:0]const u8, ...) callconv(.C) c_int; - extern "C" fn ffi_fopen([*:0]const u8, [*:0]const u8) callconv(.C) *anyopaque; - extern "C" fn ffi_fclose(*anyopaque) callconv(.C) c_int; - extern "C" fn ffi_fgetc(*anyopaque) callconv(.C) c_int; - extern "C" fn ffi_fputc(c: c_int, *anyopaque) callconv(.C) c_int; - extern "C" fn ffi_feof(*anyopaque) callconv(.C) c_int; - extern "C" fn ffi_fileno(*anyopaque) callconv(.C) c_int; - extern "C" fn ffi_ungetc(c: c_int, *anyopaque) callconv(.C) c_int; - extern "C" fn ffi_ftell(*anyopaque) callconv(.C) c_long; - extern "C" fn ffi_fseek(*anyopaque, c_long, c_int) callconv(.C) c_int; - extern "C" fn ffi_fflush(*anyopaque) callconv(.C) c_int; - - extern "C" fn calloc(nmemb: usize, size: usize) callconv(.C) ?*anyopaque; - extern "C" fn perror([*:0]const u8) callconv(.C) void; + extern "c" fn ffi_vfprintf(*anyopaque, [*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_vprintf([*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_fprintf(*anyopaque, [*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_printf([*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_fscanf(*anyopaque, [*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_scanf([*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_sscanf([*:0]const u8, [*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_vsscanf([*:0]const u8, [*:0]const u8, ...) callconv(.C) c_int; + extern "c" fn ffi_fopen([*:0]const u8, [*:0]const u8) callconv(.C) *anyopaque; + extern "c" fn ffi_fclose(*anyopaque) callconv(.C) c_int; + extern "c" fn ffi_fgetc(*anyopaque) callconv(.C) c_int; + extern "c" fn ffi_fputc(c: c_int, *anyopaque) callconv(.C) c_int; + extern "c" fn ffi_feof(*anyopaque) callconv(.C) c_int; + extern "c" fn ffi_fileno(*anyopaque) callconv(.C) c_int; + extern "c" fn ffi_ungetc(c: c_int, *anyopaque) callconv(.C) c_int; + extern "c" fn ffi_ftell(*anyopaque) callconv(.C) c_long; + extern "c" fn ffi_fseek(*anyopaque, c_long, c_int) callconv(.C) c_int; + extern "c" fn ffi_fflush(*anyopaque) callconv(.C) c_int; + + extern "c" fn calloc(nmemb: usize, size: usize) callconv(.C) ?*anyopaque; + extern "c" fn perror([*:0]const u8) callconv(.C) void; const mac = if (Environment.isMac) struct { var ffi_stdinp: *anyopaque = @extern(*anyopaque, .{ .name = "__stdinp" }); @@ -275,7 +275,9 @@ pub const FFI = struct { "macosx", "-show-sdk-path", }, - .envp = std.c.environ, + // ?[*:null]?[*:0]const u8 + // [*:null]?[*:0]u8 + .envp = @ptrCast(std.c.environ), }) catch return; if (process == .result) { defer process.result.deinit(); @@ -677,7 +679,7 @@ pub const FFI = struct { if (!value.isString()) { return globalThis.throwInvalidArgumentTypeValue("flags", "array of strings", value); } - const slice = value.toSlice(globalThis, bun.default_allocator); + const slice = try value.toSlice(globalThis, bun.default_allocator); if (slice.len == 0) continue; defer slice.deinit(); flags.append(' ') catch bun.outOfMemory(); @@ -1338,7 +1340,7 @@ pub const FFI = struct { return ZigString.static("param must be a string (type name) or number").toErrorInstance(global); } - var type_name = val.toSlice(global, allocator); + var type_name = try val.toSlice(global, allocator); defer type_name.deinit(); abi_types.appendAssumeCapacity(ABIType.label.get(type_name.slice()) orelse { abi_types.clearAndFree(allocator); @@ -1370,7 +1372,7 @@ pub const FFI = struct { } } - var ret_slice = ret_value.toSlice(global, allocator); + var ret_slice = try ret_value.toSlice(global, allocator); defer ret_slice.deinit(); return_type = ABIType.label.get(ret_slice.slice()) orelse { abi_types.clearAndFree(allocator); @@ -1469,7 +1471,7 @@ pub const FFI = struct { return val.return_type == ABIType.napi_value; } - extern "C" fn FFICallbackFunctionWrapper_destroy(*anyopaque) void; + extern "c" fn FFICallbackFunctionWrapper_destroy(*anyopaque) void; pub fn deinit(val: *Function, globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator) void { JSC.markBinding(@src()); @@ -2438,13 +2440,13 @@ const CompilerRT = struct { bun_call: *const @TypeOf(JSC.C.JSObjectCallAsFunction), }; const headers = @import("../bindings/headers.zig"); - var workaround: MyFunctionSStructWorkAround = if (!JSC.is_bindgen) .{ + var workaround: MyFunctionSStructWorkAround = .{ .JSVALUE_TO_INT64 = headers.JSC__JSValue__toInt64, .JSVALUE_TO_UINT64 = headers.JSC__JSValue__toUInt64NoTruncate, .INT64_TO_JSVALUE = headers.JSC__JSValue__fromInt64NoTruncate, .UINT64_TO_JSVALUE = headers.JSC__JSValue__fromUInt64NoTruncate, .bun_call = &JSC.C.JSObjectCallAsFunction, - } else undefined; + }; noinline fn memset( dest: [*]u8, @@ -2520,12 +2522,10 @@ const CompilerRT = struct { "JSVALUE_TO_UINT64_SLOW", workaround.JSVALUE_TO_UINT64, ); - if (!comptime JSC.is_bindgen) { - std.mem.doNotOptimizeAway(headers.JSC__JSValue__toUInt64NoTruncate); - std.mem.doNotOptimizeAway(headers.JSC__JSValue__toInt64); - std.mem.doNotOptimizeAway(headers.JSC__JSValue__fromInt64NoTruncate); - std.mem.doNotOptimizeAway(headers.JSC__JSValue__fromUInt64NoTruncate); - } + std.mem.doNotOptimizeAway(headers.JSC__JSValue__toUInt64NoTruncate); + std.mem.doNotOptimizeAway(headers.JSC__JSValue__toInt64); + std.mem.doNotOptimizeAway(headers.JSC__JSValue__fromInt64NoTruncate); + std.mem.doNotOptimizeAway(headers.JSC__JSValue__fromUInt64NoTruncate); _ = TCC.tcc_add_symbol( state, "INT64_TO_JSVALUE_SLOW", diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig index ae4d50e2c2fe82..0569d5f858d65e 100644 --- a/src/bun.js/api/filesystem_router.zig +++ b/src/bun.js/api/filesystem_router.zig @@ -1,6 +1,5 @@ const std = @import("std"); const Api = @import("../../api/schema.zig").Api; -const JavaScript = @import("../javascript.zig"); const QueryStringMap = @import("../../url.zig").QueryStringMap; const CombinedScanner = @import("../../url.zig").CombinedScanner; const bun = @import("root").bun; @@ -9,7 +8,6 @@ const JSC = bun.JSC; const js = JSC.C; const WebCore = JSC.WebCore; const Transpiler = bun.transpiler; -const VirtualMachine = JavaScript.VirtualMachine; const ScriptSrcStream = std.io.FixedBufferStream([]u8); const ZigString = JSC.ZigString; const Fs = @import("../../fs.zig"); @@ -78,7 +76,7 @@ pub const FileSystemRouter = struct { if (!dir.isString()) { return globalThis.throwInvalidArguments("Expected dir to be a string", .{}); } - const root_dir_path_ = dir.toSlice(globalThis, globalThis.allocator()); + const root_dir_path_ = try dir.toSlice(globalThis, globalThis.allocator()); if (!(root_dir_path_.len == 0 or strings.eqlComptime(root_dir_path_.slice(), "."))) { // resolve relative path if needed const path = root_dir_path_.slice(); @@ -115,7 +113,7 @@ pub const FileSystemRouter = struct { return globalThis.throwInvalidArguments("Expected fileExtensions to be an Array of strings", .{}); } if (val.getLength(globalThis) == 0) continue; - extensions.appendAssumeCapacity((val.toSlice(globalThis, allocator).clone(allocator) catch unreachable).slice()[1..]); + extensions.appendAssumeCapacity(((try val.toSlice(globalThis, allocator)).clone(allocator) catch unreachable).slice()[1..]); } } @@ -127,7 +125,7 @@ pub const FileSystemRouter = struct { return globalThis.throwInvalidArguments("Expected assetPrefix to be a string", .{}); } - asset_prefix_slice = asset_prefix.toSlice(globalThis, allocator).clone(allocator) catch unreachable; + asset_prefix_slice = (try asset_prefix.toSlice(globalThis, allocator)).clone(allocator) catch unreachable; } const orig_log = vm.transpiler.resolver.log; var log = Log.Log.init(allocator); @@ -167,7 +165,7 @@ pub const FileSystemRouter = struct { globalThis.allocator().destroy(arena); return globalThis.throwInvalidArguments("Expected origin to be a string", .{}); } - origin_str = origin.toSlice(globalThis, globalThis.allocator()); + origin_str = try origin.toSlice(globalThis, globalThis.allocator()); } if (log.errors + log.warnings > 0) { @@ -299,7 +297,7 @@ pub const FileSystemRouter = struct { var path: ZigString.Slice = brk: { if (argument.isString()) { - break :brk argument.toSlice(globalThis, globalThis.allocator()).clone(globalThis.allocator()) catch unreachable; + break :brk (try argument.toSlice(globalThis, globalThis.allocator())).clone(globalThis.allocator()) catch unreachable; } if (argument.isCell()) { @@ -605,7 +603,7 @@ pub const MatchedRoute = struct { var writer = stream.writer(); JSC.API.Bun.getPublicPathWithAssetPrefix( this.route.file_path, - if (this.base_dir) |base_dir| base_dir.slice() else VirtualMachine.get().transpiler.fs.top_level_dir, + if (this.base_dir) |base_dir| base_dir.slice() else JSC.VirtualMachine.get().transpiler.fs.top_level_dir, if (this.origin) |origin| URL.parse(origin.slice()) else URL{}, if (this.asset_prefix) |prefix| prefix.slice() else "", @TypeOf(&writer), diff --git a/src/bun.js/api/glob.zig b/src/bun.js/api/glob.zig index 3ace3a87deb49f..b75a29da95f914 100644 --- a/src/bun.js/api/glob.zig +++ b/src/bun.js/api/glob.zig @@ -39,7 +39,7 @@ const ScanOpts = struct { error_on_broken_symlinks: bool, fn parseCWD(globalThis: *JSGlobalObject, allocator: std.mem.Allocator, cwdVal: JSC.JSValue, absolute: bool, comptime fnName: string) bun.JSError![]const u8 { - const cwd_str_raw = cwdVal.toSlice(globalThis, allocator); + const cwd_str_raw = try cwdVal.toSlice(globalThis, allocator); if (cwd_str_raw.len == 0) return ""; const cwd_str = cwd_str: { @@ -324,17 +324,14 @@ pub fn finalize( } pub fn hasPendingActivity(this: *Glob) callconv(.C) bool { - @fence(.seq_cst); return this.has_pending_activity.load(.seq_cst) > 0; } fn incrPendingActivityFlag(has_pending_activity: *std.atomic.Value(usize)) void { - @fence(.seq_cst); _ = has_pending_activity.fetchAdd(1, .seq_cst); } fn decrPendingActivityFlag(has_pending_activity: *std.atomic.Value(usize)) void { - @fence(.seq_cst); _ = has_pending_activity.fetchSub(1, .seq_cst); } @@ -403,7 +400,7 @@ pub fn match(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFrame return globalThis.throw("Glob.matchString: first argument is not a string", .{}); } - var str = str_arg.toSlice(globalThis, arena.allocator()); + var str = try str_arg.toSlice(globalThis, arena.allocator()); defer str.deinit(); if (this.is_ascii and isAllAscii(str.slice())) return JSC.JSValue.jsBoolean(globImpl.Ascii.match(this.pattern, str.slice()).matches()); diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 4ab5a5c9b1dbf1..f8f835fbb341e1 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -18,7 +18,7 @@ pub const LOLHTMLContext = struct { document_handlers: std.ArrayListUnmanaged(*DocumentHandler) = .{}, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); fn deinit(this: *LOLHTMLContext) void { for (this.selectors.items) |selector| { @@ -189,7 +189,7 @@ pub const HTMLRewriter = struct { const kind: ResponseKind = brk: { if (response_value.isString()) break :brk .string - else if (response_value.jsType().isTypedArray()) + else if (response_value.jsType().isTypedArrayOrArrayBuffer()) break :brk .array_buffer else break :brk .other; @@ -395,7 +395,7 @@ pub const HTMLRewriter = struct { bodyValueBufferer: ?JSC.WebCore.BodyValueBufferer = null, tmp_sync_error: ?*JSC.JSValue = null, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(BufferOutputSink, deinit); + pub usingnamespace bun.NewRefCounted(BufferOutputSink, deinit, null); // const log = bun.Output.scoped(.BufferOutputSink, false); pub fn init(context: *LOLHTMLContext, global: *JSGlobalObject, original: *Response, builder: *LOLHTML.HTMLRewriter.Builder) JSC.JSValue { @@ -1066,7 +1066,7 @@ pub const TextChunk = struct { ref_count: u32 = 1, pub usingnamespace JSC.Codegen.JSTextChunk; - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub fn init(text_chunk: *LOLHTML.TextChunk) *TextChunk { return TextChunk.new(.{ .text_chunk = text_chunk, .ref_count = 2 }); } @@ -1175,7 +1175,7 @@ pub const DocType = struct { return DocType.new(.{ .doctype = doctype, .ref_count = 2 }); } - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub usingnamespace JSC.Codegen.JSDocType; /// The doctype name. @@ -1242,7 +1242,7 @@ pub const DocEnd = struct { doc_end: ?*LOLHTML.DocEnd, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub usingnamespace JSC.Codegen.JSDocEnd; pub fn init(doc_end: *LOLHTML.DocEnd) *DocEnd { @@ -1291,7 +1291,7 @@ pub const Comment = struct { comment: ?*LOLHTML.Comment = null, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub usingnamespace JSC.Codegen.JSComment; pub fn init(comment: *LOLHTML.Comment) *Comment { @@ -1374,7 +1374,7 @@ pub const Comment = struct { ) callconv(.C) bool { if (this.comment == null) return false; - var text = value.toSlice(global, bun.default_allocator); + var text = value.toSlice(global, bun.default_allocator) catch return false; defer text.deinit(); this.comment.?.setText(text.slice()) catch { global.throwValue(createLOLHTMLError(global)) catch {}; @@ -1436,7 +1436,7 @@ pub const EndTag = struct { }; pub usingnamespace JSC.Codegen.JSEndTag; - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); fn contentHandler(this: *EndTag, comptime Callback: (fn (*LOLHTML.EndTag, []const u8, bool) LOLHTML.Error!void), thisObject: JSValue, globalObject: *JSGlobalObject, content: ZigString, contentOptions: ?ContentOptions) JSValue { if (this.end_tag == null) @@ -1517,7 +1517,7 @@ pub const EndTag = struct { ) callconv(.C) bool { if (this.end_tag == null) return false; - var text = value.toSlice(global, bun.default_allocator); + var text = value.toSlice(global, bun.default_allocator) catch return false; defer text.deinit(); this.end_tag.?.setName(text.slice()) catch { global.throwValue(createLOLHTMLError(global)) catch {}; @@ -1554,7 +1554,7 @@ pub const AttributeIterator = struct { } pub usingnamespace JSC.Codegen.JSAttributeIterator; - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub fn next(this: *AttributeIterator, globalObject: *JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSValue { const done_label = JSC.ZigString.static("done"); @@ -1591,7 +1591,7 @@ pub const Element = struct { ref_count: u32 = 1, pub usingnamespace JSC.Codegen.JSElement; - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub fn init(element: *LOLHTML.Element) *Element { return Element.new(.{ .element = element, .ref_count = 2 }); @@ -1826,8 +1826,7 @@ pub const Element = struct { ) bool { if (this.element == null) return false; - - var text = value.toSlice(global, bun.default_allocator); + var text = value.toSlice(global, bun.default_allocator) catch return false; defer text.deinit(); this.element.?.setTagName(text.slice()) catch { diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index f6f95f30a95162..6b04ccd5ae3439 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -69,7 +69,6 @@ const Config = @import("../config.zig"); const URL = @import("../../url.zig").URL; const VirtualMachine = JSC.VirtualMachine; const IOTask = JSC.IOTask; -const is_bindgen = JSC.is_bindgen; const uws = bun.uws; const Fallback = Runtime.Fallback; const MimeType = HTTP.MimeType; @@ -270,6 +269,7 @@ pub const ServerConfig = struct { reuse_port: bool = false, id: []const u8 = "", allow_hot: bool = true, + ipv6_only: bool = false, static_routes: std.ArrayList(StaticRouteEntry) = std.ArrayList(StaticRouteEntry).init(bun.default_allocator), @@ -449,6 +449,20 @@ pub const ServerConfig = struct { return arraylist.items; } + pub fn getUsocketsOptions(this: *const ServerConfig) i32 { + // Unlike Node.js, we set exclusive port in case reuse port is not set + var out: i32 = if (this.reuse_port) + uws.LIBUS_LISTEN_REUSE_PORT | uws.LIBUS_LISTEN_REUSE_ADDR + else + uws.LIBUS_LISTEN_EXCLUSIVE_PORT; + + if (this.ipv6_only) { + out |= uws.LIBUS_SOCKET_IPV6_ONLY; + } + + return out; + } + pub const SSLConfig = struct { requires_custom_request_ctx: bool = false, server_name: [*c]const u8 = null, @@ -662,7 +676,7 @@ pub const ServerConfig = struct { // Required if (try obj.getTruthy(global, "keyFile")) |key_file_name| { - var sliced = key_file_name.toSlice(global, bun.default_allocator); + var sliced = try key_file_name.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.key_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -754,7 +768,7 @@ pub const ServerConfig = struct { } if (try obj.getTruthy(global, "certFile")) |cert_file_name| { - var sliced = cert_file_name.toSlice(global, bun.default_allocator); + var sliced = try cert_file_name.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.cert_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -880,7 +894,7 @@ pub const ServerConfig = struct { } if (try obj.getTruthy(global, "ciphers")) |ssl_ciphers| { - var sliced = ssl_ciphers.toSlice(global, bun.default_allocator); + var sliced = try ssl_ciphers.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.ssl_ciphers = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -890,7 +904,7 @@ pub const ServerConfig = struct { } if (try obj.getTruthy(global, "serverName") orelse try obj.getTruthy(global, "servername")) |server_name| { - var sliced = server_name.toSlice(global, bun.default_allocator); + var sliced = try server_name.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.server_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -979,7 +993,7 @@ pub const ServerConfig = struct { } if (try obj.getTruthy(global, "caFile")) |ca_file_name| { - var sliced = ca_file_name.toSlice(global, bun.default_allocator); + var sliced = try ca_file_name.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.ca_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -1009,7 +1023,7 @@ pub const ServerConfig = struct { } if (try obj.getTruthy(global, "dhParamsFile")) |dh_params_file_name| { - var sliced = dh_params_file_name.toSlice(global, bun.default_allocator); + var sliced = try dh_params_file_name.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.dh_params_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -1020,7 +1034,7 @@ pub const ServerConfig = struct { } if (try obj.getTruthy(global, "passphrase")) |passphrase| { - var sliced = passphrase.toSlice(global, bun.default_allocator); + var sliced = try passphrase.toSlice(global, bun.default_allocator); defer sliced.deinit(); if (sliced.len > 0) { result.passphrase = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; @@ -1096,7 +1110,7 @@ pub const ServerConfig = struct { var port = args.address.tcp.port; if (arguments.vm.transpiler.options.transform_options.origin) |origin| { - args.base_uri = origin; + args.base_uri = try bun.default_allocator.dupeZ(u8, origin); } defer { @@ -1136,16 +1150,15 @@ pub const ServerConfig = struct { while (try iter.next()) |key| { const path, const is_ascii = key.toOwnedSliceReturningAllASCII(bun.default_allocator) catch bun.outOfMemory(); + errdefer bun.default_allocator.free(path); const value = iter.value; - if (path.len == 0 or path[0] != '/') { - bun.default_allocator.free(path); + if (path.len == 0 or (path[0] != '/' and path[0] != '*')) { return global.throwInvalidArguments("Invalid static route \"{s}\". path must start with '/'", .{path}); } if (!is_ascii) { - bun.default_allocator.free(path); return global.throwInvalidArguments("Invalid static route \"{s}\". Please encode all non-ASCII characters in the path.", .{path}); } @@ -1201,10 +1214,13 @@ pub const ServerConfig = struct { if (global.hasException()) return error.JSError; if (try arg.getTruthy(global, "baseURI")) |baseURI| { - var sliced = baseURI.toSlice(global, bun.default_allocator); + var sliced = try baseURI.toSlice(global, bun.default_allocator); if (sliced.len > 0) { defer sliced.deinit(); + if (args.base_uri.len > 0) { + bun.default_allocator.free(@constCast(args.base_uri)); + } args.base_uri = bun.default_allocator.dupe(u8, sliced.slice()) catch unreachable; } } @@ -1240,7 +1256,7 @@ pub const ServerConfig = struct { if (id.isUndefinedOrNull()) { args.allow_hot = false; } else { - const id_str = id.toSlice( + const id_str = try id.toSlice( global, bun.default_allocator, ); @@ -1279,6 +1295,11 @@ pub const ServerConfig = struct { } if (global.hasException()) return error.JSError; + if (try arg.get(global, "ipv6Only")) |dev| { + args.ipv6_only = dev.coerce(bool, global); + } + if (global.hasException()) return error.JSError; + if (try arg.get(global, "inspector")) |inspector| { args.inspector = inspector.coerce(bool, global); @@ -1394,6 +1415,8 @@ pub const ServerConfig = struct { const protocol: string = if (args.ssl_config != null) "https" else "http"; const hostname = args.base_url.hostname; const needsBrackets: bool = strings.isIPV6Address(hostname) and hostname[0] != '['; + const original_base_uri = args.base_uri; + defer bun.default_allocator.free(@constCast(original_base_uri)); if (needsBrackets) { args.base_uri = (if ((port == 80 and args.ssl_config == null) or (port == 443 and args.ssl_config != null)) std.fmt.allocPrint(bun.default_allocator, "{s}://[{s}]/{s}", .{ @@ -1588,7 +1611,7 @@ pub const AnyRequestContext = struct { tagged_pointer: Pointer, - pub const Null = .{ .tagged_pointer = Pointer.Null }; + pub const Null: @This() = .{ .tagged_pointer = Pointer.Null }; pub fn init(request_ctx: anytype) AnyRequestContext { return .{ .tagged_pointer = Pointer.init(request_ctx) }; @@ -2732,7 +2755,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp } } - pub fn onReadFile(this: *RequestContext, result: Blob.ReadFile.ResultType) void { + pub fn onReadFile(this: *RequestContext, result: Blob.ReadFileResultType) void { defer this.deref(); if (this.isAbortedOrEnded()) { @@ -3036,6 +3059,9 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp } fn endRequestStreaming(this: *RequestContext) bool { assert(this.server != null); + + this.request_body_buf.clearAndFree(bun.default_allocator); + // if we cannot, we have to reject pending promises // first, we reject the request body promise if (this.request_body) |body| { @@ -3049,6 +3075,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp return false; } fn detachResponse(this: *RequestContext) void { + this.request_body_buf.clearAndFree(bun.default_allocator); + if (this.resp) |resp| { this.resp = null; @@ -4102,7 +4130,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp var body = this.request_body.?; var old = body.value; old.Locked.onReceiveValue = null; - var new_body = .{ .Null = {} }; + var new_body: WebCore.Body.Value = .{ .Null = {} }; old.resolve(&new_body, server.globalThis, null); body.value = new_body; } @@ -4158,13 +4186,13 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp comptime { const jsonResolve = JSC.toJSHostFunction(onResolve); - @export(jsonResolve, .{ .name = Export[0].symbol_name }); + @export(&jsonResolve, .{ .name = Export[0].symbol_name }); const jsonReject = JSC.toJSHostFunction(onReject); - @export(jsonReject, .{ .name = Export[1].symbol_name }); + @export(&jsonReject, .{ .name = Export[1].symbol_name }); const jsonResolveStream = JSC.toJSHostFunction(onResolveStream); - @export(jsonResolveStream, .{ .name = Export[2].symbol_name }); + @export(&jsonResolveStream, .{ .name = Export[2].symbol_name }); const jsonRejectStream = JSC.toJSHostFunction(onRejectStream); - @export(jsonRejectStream, .{ .name = Export[3].symbol_name }); + @export(&jsonRejectStream, .{ .name = Export[3].symbol_name }); } }; } @@ -4643,11 +4671,7 @@ pub const ServerWebSocket = struct { const arguments = [_]JSValue{ this.getThisValue(), switch (opcode) { - .text => brk: { - var str = ZigString.init(message); - str.markUTF8(); - break :brk str.toJS(globalObject); - }, + .text => bun.String.createUTF8ForJS(globalObject, message), .binary => this.binaryToJS(globalObject, message), else => unreachable, }, @@ -4811,13 +4835,12 @@ pub const ServerWebSocket = struct { } if (!handler.onClose.isEmptyOrUndefinedOrNull()) { - var str = ZigString.init(message); const globalObject = handler.globalObject; const loop = vm.eventLoop(); loop.enter(); defer loop.exit(); - str.markUTF8(); + if (signal) |sig| { if (!sig.aborted()) { sig.signal(handler.globalObject, .ConnectionClosed); @@ -4827,7 +4850,7 @@ pub const ServerWebSocket = struct { _ = handler.onClose.call( globalObject, .undefined, - &[_]JSC.JSValue{ this.getThisValue(), JSValue.jsNumber(code), str.toJS(globalObject) }, + &[_]JSC.JSValue{ this.getThisValue(), JSValue.jsNumber(code), bun.String.createUTF8ForJS(globalObject, message) }, ) catch |e| { const err = globalObject.takeException(e); log("onClose error", .{}); @@ -4888,7 +4911,7 @@ pub const ServerWebSocket = struct { return globalThis.throw("publish requires a topic string", .{}); } - var topic_slice = topic_value.toSlice(globalThis, bun.default_allocator); + var topic_slice = try topic_value.toSlice(globalThis, bun.default_allocator); defer topic_slice.deinit(); if (topic_slice.len == 0) { return globalThis.throw("publish requires a non-empty topic", .{}); @@ -4976,7 +4999,7 @@ pub const ServerWebSocket = struct { return globalThis.throw("publishText requires a topic string", .{}); } - var topic_slice = topic_value.toSlice(globalThis, bun.default_allocator); + var topic_slice = try topic_value.toSlice(globalThis, bun.default_allocator); defer topic_slice.deinit(); if (!compress_value.isBoolean() and !compress_value.isUndefined() and compress_value != .zero) { @@ -5041,7 +5064,7 @@ pub const ServerWebSocket = struct { return globalThis.throw("publishBinary requires a topic string", .{}); } - var topic_slice = topic_value.toSlice(globalThis, bun.default_allocator); + var topic_slice = try topic_value.toSlice(globalThis, bun.default_allocator); defer topic_slice.deinit(); if (topic_slice.len == 0) { return globalThis.throw("publishBinary requires a non-empty topic", .{}); @@ -5685,7 +5708,7 @@ pub const ServerWebSocket = struct { return globalThis.throwInvalidArgumentTypeValue("topic", "string", args.ptr[0]); } - var topic = args.ptr[0].toSlice(globalThis, bun.default_allocator); + var topic = try args.ptr[0].toSlice(globalThis, bun.default_allocator); defer topic.deinit(); if (topic.len == 0) { @@ -5708,7 +5731,7 @@ pub const ServerWebSocket = struct { return globalThis.throwInvalidArgumentTypeValue("topic", "string", args.ptr[0]); } - var topic = args.ptr[0].toSlice(globalThis, bun.default_allocator); + var topic = try args.ptr[0].toSlice(globalThis, bun.default_allocator); defer topic.deinit(); if (topic.len == 0) { @@ -5735,7 +5758,7 @@ pub const ServerWebSocket = struct { return globalThis.throwInvalidArgumentTypeValue("topic", "string", args.ptr[0]); } - var topic = args.ptr[0].toSlice(globalThis, bun.default_allocator); + var topic = try args.ptr[0].toSlice(globalThis, bun.default_allocator); defer topic.deinit(); if (topic.len == 0) { @@ -5764,7 +5787,7 @@ pub const ServerWebSocket = struct { }; const text = bun.fmt.formatIp(address, &text_buf) catch unreachable; - return ZigString.init(text).toJS(globalThis); + return bun.String.createUTF8ForJS(globalThis, text); } }; @@ -5772,7 +5795,7 @@ const ServePlugins = struct { value: Value, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(ServePlugins, deinit); + pub usingnamespace bun.NewRefCounted(ServePlugins, deinit, null); pub const Value = union(enum) { pending: struct { @@ -5930,8 +5953,8 @@ const ServePlugins = struct { } comptime { - @export(onResolve, .{ .name = "BunServe__onResolvePlugins" }); - @export(onReject, .{ .name = "BunServe__onRejectPlugins" }); + @export(&onResolve, .{ .name = "BunServe__onResolvePlugins" }); + @export(&onReject, .{ .name = "BunServe__onRejectPlugins" }); } }; @@ -6042,11 +6065,8 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return globalThis.throwInvalidArguments("subscriberCount requires a topic name as a string", .{}); } - var topic = arguments.ptr[0].toSlice(globalThis, bun.default_allocator); + var topic = try arguments.ptr[0].toSlice(globalThis, bun.default_allocator); defer topic.deinit(); - if (globalThis.hasException()) { - return .zero; - } if (topic.len == 0) { return JSValue.jsNumber(0); @@ -6075,7 +6095,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return if (request.request_context.getRemoteSocketInfo()) |info| JSSocketAddress__create( this.globalThis, - bun.String.init(info.ip).toJS(this.globalThis), + bun.String.createUTF8ForJS(this.globalThis, info.ip), info.port, info.is_ipv6, ) @@ -6432,7 +6452,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp // TODO: set User-Agent header // TODO: unify with fetch() implementation. if (first_arg.isString()) { - const url_zig_str = arguments[0].toSlice(ctx, bun.default_allocator); + const url_zig_str = try arguments[0].toSlice(ctx, bun.default_allocator); defer url_zig_str.deinit(); var temp_url_str = url_zig_str.slice(); @@ -6455,7 +6475,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp if (arguments.len >= 2 and arguments[1].isObject()) { var opts = arguments[1]; if (opts.fastGet(ctx, .method)) |method_| { - var slice_ = method_.toSlice(ctx, getAllocator(ctx)); + var slice_ = try method_.toSlice(ctx, getAllocator(ctx)); defer slice_.deinit(); method = HTTP.Method.which(slice_.slice()) orelse method; } @@ -7433,8 +7453,30 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp if (this.dev_server) |dev| { dev.attachRoutes(this) catch bun.outOfMemory(); } else { - bun.assert(this.config.onRequest != .zero); - app.any("/*", *ThisServer, this, onRequest); + const @"has /*" = brk: { + for (this.config.static_routes.items) |route| { + if (strings.eqlComptime(route.path, "/*")) { + break :brk true; + } + } + + break :brk false; + }; + + // "/*" routes are added backwards, so if they have a static route, it will never be matched + // so we need to check for that first + if (!@"has /*") { + bun.assert(this.config.onRequest != .zero); + app.any("/*", *ThisServer, this, onRequest); + } else if (this.config.onRequest != .zero) { + app.post("/*", *ThisServer, this, onRequest); + app.put("/*", *ThisServer, this, onRequest); + app.patch("/*", *ThisServer, this, onRequest); + app.delete("/*", *ThisServer, this, onRequest); + app.options("/*", *ThisServer, this, onRequest); + app.trace("/*", *ThisServer, this, onRequest); + app.connect("/*", *ThisServer, this, onRequest); + } } } @@ -7554,8 +7596,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp app.listenWithConfig(*ThisServer, this, onListen, .{ .port = tcp.port, .host = host, - // IPV6_ONLY is the default for bun, different from node it also set exclusive port in case reuse port is not set - .options = (if (this.config.reuse_port) uws.LIBUS_SOCKET_REUSE_PORT else uws.LIBUS_LISTEN_EXCLUSIVE_PORT) | uws.LIBUS_SOCKET_IPV6_ONLY, + .options = this.config.getUsocketsOptions(), }); }, @@ -7565,8 +7606,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this, onListen, unix, - // IPV6_ONLY is the default for bun, different from node it also set exclusive port in case reuse port is not set - (if (this.config.reuse_port) uws.LIBUS_SOCKET_REUSE_PORT else uws.LIBUS_LISTEN_EXCLUSIVE_PORT) | uws.LIBUS_SOCKET_IPV6_ONLY, + this.config.getUsocketsOptions(), ); }, } @@ -7770,9 +7810,7 @@ pub fn Server__setIdleTimeout_(server: JSC.JSValue, seconds: JSC.JSValue, global } comptime { - if (!JSC.is_bindgen) { - _ = Server__setIdleTimeout; - } + _ = Server__setIdleTimeout; } fn throwSSLErrorIfNecessary(globalThis: *JSC.JSGlobalObject) bool { diff --git a/src/bun.js/api/server/HTMLBundle.zig b/src/bun.js/api/server/HTMLBundle.zig index 082ecd26734dd5..5af4f1b8d2a10a 100644 --- a/src/bun.js/api/server/HTMLBundle.zig +++ b/src/bun.js/api/server/HTMLBundle.zig @@ -16,7 +16,12 @@ bunfig_dir: []const u8, /// `plugins` is array of serve plugins defined in the bunfig.toml file. They will be resolved and loaded. /// `bunfig_path` is the path to the bunfig.toml configuration file. It used to resolve the plugins relative /// to the bunfig.toml file. -pub fn init(globalObject: *JSGlobalObject, path: []const u8, bunfig_path: []const u8, plugins: ?[]const []const u8) !*HTMLBundle { +pub fn init( + globalObject: *JSGlobalObject, + path: []const u8, + bunfig_path: []const u8, + plugins: ?[]const []const u8, +) !*HTMLBundle { var config = bun.JSC.API.JSBundler.Config{}; try config.entry_points.insert(path); config.target = .browser; @@ -63,6 +68,7 @@ pub const HTMLBundleRoute = struct { } pub fn init(html_bundle: *HTMLBundle) *HTMLBundleRoute { + html_bundle.ref(); return HTMLBundleRoute.new(.{ .html_bundle = html_bundle, .pending_responses = .{}, @@ -72,7 +78,7 @@ pub const HTMLBundleRoute = struct { }); } - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); + pub usingnamespace bun.NewRefCounted(@This(), _deinit, null); pub const Value = union(enum) { pending_plugins, @@ -109,7 +115,7 @@ pub const HTMLBundleRoute = struct { } }; - pub fn deinit(this: *HTMLBundleRoute) void { + fn _deinit(this: *HTMLBundleRoute) void { for (this.pending_responses.items) |pending_response| { pending_response.deref(); } @@ -261,12 +267,33 @@ pub const HTMLBundleRoute = struct { config.entry_points = config.entry_points.clone() catch bun.outOfMemory(); config.public_path = config.public_path.clone() catch bun.outOfMemory(); config.define = config.define.clone() catch bun.outOfMemory(); - if (!server.config().development) { - config.minify.syntax = true; - config.minify.whitespace = true; + + if (bun.CLI.Command.get().args.serve_minify_identifiers) |minify_identifiers| { + config.minify.identifiers = minify_identifiers; + } else if (!server.config().development) { config.minify.identifiers = true; + } + + if (bun.CLI.Command.get().args.serve_minify_whitespace) |minify_whitespace| { + config.minify.whitespace = minify_whitespace; + } else if (!server.config().development) { + config.minify.whitespace = true; + } + + if (bun.CLI.Command.get().args.serve_minify_syntax) |minify_syntax| { + config.minify.syntax = minify_syntax; + } else if (!server.config().development) { + config.minify.syntax = true; + } + + if (!server.config().development) { config.define.put("process.env.NODE_ENV", "\"production\"") catch bun.outOfMemory(); + config.jsx.development = false; + } else { + config.force_node_env = .development; + config.jsx.development = true; } + config.source_map = .linked; const completion_task = bun.BundleV2.createAndScheduleCompletionTask( @@ -490,9 +517,9 @@ pub const HTMLBundleRoute = struct { server: ?AnyServer = null, route: *HTMLBundleRoute, - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); + pub usingnamespace bun.NewRefCounted(@This(), __deinit, null); - pub fn deinit(this: *PendingResponse) void { + fn __deinit(this: *PendingResponse) void { if (this.is_response_pending) { this.resp.clearAborted(); this.resp.clearOnWritable(); @@ -522,7 +549,7 @@ pub const HTMLBundleRoute = struct { }; pub usingnamespace JSC.Codegen.JSHTMLBundle; -pub usingnamespace bun.NewRefCounted(HTMLBundle, deinit); +pub usingnamespace bun.NewRefCounted(HTMLBundle, deinit, null); const bun = @import("root").bun; const std = @import("std"); const JSC = bun.JSC; diff --git a/src/bun.js/api/server/StaticRoute.zig b/src/bun.js/api/server/StaticRoute.zig index 31336978771a8d..7270198b051b48 100644 --- a/src/bun.js/api/server/StaticRoute.zig +++ b/src/bun.js/api/server/StaticRoute.zig @@ -10,7 +10,7 @@ headers: Headers = .{ }, ref_count: u32 = 1, -pub usingnamespace bun.NewRefCounted(@This(), deinit); +pub usingnamespace bun.NewRefCounted(@This(), deinit, null); fn deinit(this: *StaticRoute) void { this.blob.detach(); diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index a81413f87b2413..01c099782e2fa2 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -9,18 +9,11 @@ const strings = bun.strings; const MutableString = bun.MutableString; const stringZ = bun.stringZ; const default_allocator = bun.default_allocator; -const C = bun.C; -const JavaScript = @import("./javascript.zig"); const JSC = bun.JSC; -const WebCore = @import("./webcore.zig"); const Test = @import("./test/jest.zig"); -const Fetch = WebCore.Fetch; -const Response = WebCore.Response; -const Request = WebCore.Request; const Router = @import("./api/filesystem_router.zig"); const IdentityContext = @import("../identity_context.zig").IdentityContext; const uws = bun.uws; -const Body = WebCore.Body; const TaggedPointerTypes = @import("../tagged_pointer.zig"); const TaggedPointerUnion = TaggedPointerTypes.TaggedPointerUnion; @@ -41,11 +34,11 @@ pub const Lifetime = enum { pub fn toJS(globalObject: *JSC.JSGlobalObject, comptime ValueType: type, value: ValueType, comptime lifetime: Lifetime) JSC.JSValue { const Type = comptime brk: { var CurrentType = ValueType; - if (@typeInfo(ValueType) == .Optional) { - CurrentType = @typeInfo(ValueType).Optional.child; + if (@typeInfo(ValueType) == .optional) { + CurrentType = @typeInfo(ValueType).optional.child; } - break :brk if (@typeInfo(CurrentType) == .Pointer and @typeInfo(CurrentType).Pointer.size == .One) - @typeInfo(CurrentType).Pointer.child + break :brk if (@typeInfo(CurrentType) == .pointer and @typeInfo(CurrentType).pointer.size == .one) + @typeInfo(CurrentType).pointer.child else CurrentType; }; @@ -72,6 +65,18 @@ pub fn toJS(globalObject: *JSC.JSGlobalObject, comptime ValueType: type, value: }, JSC.JSValue => return if (Type != ValueType) value.* else value, + inline []const u16, []const u32, []const i16, []const i8, []const i32, []const f32 => { + var array = JSC.JSValue.createEmptyArray(globalObject, value.len); + for (value, 0..) |item, i| { + array.putIndex( + globalObject, + @truncate(i), + JSC.jsNumber(item), + ); + } + return array; + }, + else => { // Recursion can stack overflow here @@ -80,7 +85,7 @@ pub fn toJS(globalObject: *JSC.JSGlobalObject, comptime ValueType: type, value: var array = JSC.JSValue.createEmptyArray(globalObject, value.len); for (value, 0..) |*item, i| { - const res = toJS(globalObject, *const Child, item, lifetime); + const res = toJS(globalObject, *Child, item, lifetime); if (res == .zero) return .zero; array.putIndex( globalObject, @@ -91,16 +96,16 @@ pub fn toJS(globalObject: *JSC.JSGlobalObject, comptime ValueType: type, value: return array; } - if (comptime @hasDecl(Type, "toJSNewlyCreated") and @typeInfo(@TypeOf(@field(Type, "toJSNewlyCreated"))).Fn.params.len == 2) { + if (comptime @hasDecl(Type, "toJSNewlyCreated") and @typeInfo(@TypeOf(@field(Type, "toJSNewlyCreated"))).@"fn".params.len == 2) { return value.toJSNewlyCreated(globalObject); } - if (comptime @hasDecl(Type, "toJS") and @typeInfo(@TypeOf(@field(Type, "toJS"))).Fn.params.len == 2) { + if (comptime @hasDecl(Type, "toJS") and @typeInfo(@TypeOf(@field(Type, "toJS"))).@"fn".params.len == 2) { return value.toJS(globalObject); } // must come after toJS check in case this enum implements its own serializer. - if (@typeInfo(Type) == .Enum) { + if (@typeInfo(Type) == .@"enum") { // FIXME: creates non-normalized integers (e.g. u2), which // aren't handled by `jsNumberWithType` rn return JSC.JSValue.jsNumberWithType(u32, @as(u32, @intFromEnum(value))); @@ -156,9 +161,6 @@ pub const Properties = struct { } }; -const JSValue = JSC.JSValue; -const ZigString = JSC.ZigString; - pub const PathString = bun.PathString; pub fn createError( @@ -193,7 +195,7 @@ fn toTypeErrorWithCode( args: anytype, ctx: js.JSContextRef, ) JSC.JSValue { - @setCold(true); + @branchHint(.cold); var zig_str: JSC.ZigString = undefined; if (comptime std.meta.fields(@TypeOf(args)).len == 0) { zig_str = JSC.ZigString.init(fmt); @@ -204,7 +206,7 @@ fn toTypeErrorWithCode( zig_str.detectEncoding(); zig_str.mark(); } - const code_str = ZigString.init(code); + const code_str = JSC.ZigString.init(code); return JSC.JSValue.createTypeError(&zig_str, &code_str, ctx); } @@ -223,7 +225,7 @@ pub fn throwInvalidArguments( ctx: js.JSContextRef, exception: ExceptionValueRef, ) void { - @setCold(true); + @branchHint(.cold); exception.* = JSC.Error.ERR_INVALID_ARG_TYPE.fmt(ctx, fmt, args).asObjectRef(); } @@ -232,7 +234,7 @@ pub fn toInvalidArguments( args: anytype, ctx: js.JSContextRef, ) JSC.JSValue { - @setCold(true); + @branchHint(.cold); return JSC.Error.ERR_INVALID_ARG_TYPE.fmt(ctx, fmt, args); } @@ -241,7 +243,7 @@ pub fn getAllocator(_: js.JSContextRef) std.mem.Allocator { } /// Print a JSValue to stdout; this is only meant for debugging purposes -pub fn dump(value: JSValue, globalObject: *JSC.JSGlobalObject) !void { +pub fn dump(value: JSC.WebCore.JSValue, globalObject: *JSC.JSGlobalObject) !void { var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalObject }; try Output.errorWriter().print("{}\n", .{value.toFmt(globalObject, &formatter)}); Output.flush(); @@ -377,7 +379,7 @@ pub const ArrayBuffer = extern struct { return Stream{ .pos = 0, .buf = this.slice() }; } - pub fn create(globalThis: *JSC.JSGlobalObject, bytes: []const u8, comptime kind: JSValue.JSType) JSValue { + pub fn create(globalThis: *JSC.JSGlobalObject, bytes: []const u8, comptime kind: JSC.JSValue.JSType) JSC.JSValue { JSC.markBinding(@src()); return switch (comptime kind) { .Uint8Array => Bun__createUint8ArrayForCopy(globalThis, bytes.ptr, bytes.len, false), @@ -386,7 +388,7 @@ pub const ArrayBuffer = extern struct { }; } - pub fn createEmpty(globalThis: *JSC.JSGlobalObject, comptime kind: JSC.JSValue.JSType) JSValue { + pub fn createEmpty(globalThis: *JSC.JSGlobalObject, comptime kind: JSC.JSValue.JSType) JSC.JSValue { JSC.markBinding(@src()); return switch (comptime kind) { @@ -396,18 +398,18 @@ pub const ArrayBuffer = extern struct { }; } - pub fn createBuffer(globalThis: *JSC.JSGlobalObject, bytes: []const u8) JSValue { + pub fn createBuffer(globalThis: *JSC.JSGlobalObject, bytes: []const u8) JSC.JSValue { JSC.markBinding(@src()); return Bun__createUint8ArrayForCopy(globalThis, bytes.ptr, bytes.len, true); } - pub fn createUint8Array(globalThis: *JSC.JSGlobalObject, bytes: []const u8) JSValue { + pub fn createUint8Array(globalThis: *JSC.JSGlobalObject, bytes: []const u8) JSC.JSValue { JSC.markBinding(@src()); return Bun__createUint8ArrayForCopy(globalThis, bytes.ptr, bytes.len, false); } - extern "C" fn Bun__allocUint8ArrayForCopy(*JSC.JSGlobalObject, usize, **anyopaque) JSValue; - pub fn allocBuffer(globalThis: *JSC.JSGlobalObject, len: usize) struct { JSValue, []u8 } { + extern "c" fn Bun__allocUint8ArrayForCopy(*JSC.JSGlobalObject, usize, **anyopaque) JSC.JSValue; + pub fn allocBuffer(globalThis: *JSC.JSGlobalObject, len: usize) struct { JSC.JSValue, []u8 } { var ptr: [*]u8 = undefined; const buffer = Bun__allocUint8ArrayForCopy(globalThis, len, @ptrCast(&ptr)); if (buffer.isEmpty()) { @@ -416,8 +418,8 @@ pub const ArrayBuffer = extern struct { return .{ buffer, ptr[0..len] }; } - extern "C" fn Bun__createUint8ArrayForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize, buffer: bool) JSValue; - extern "C" fn Bun__createArrayBufferForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize) JSValue; + extern "c" fn Bun__createUint8ArrayForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize, buffer: bool) JSC.JSValue; + extern "c" fn Bun__createArrayBufferForCopy(*JSC.JSGlobalObject, ptr: ?*const anyopaque, len: usize) JSC.JSValue; pub fn fromTypedArray(ctx: JSC.C.JSContextRef, value: JSC.JSValue) ArrayBuffer { var out = std.mem.zeroes(ArrayBuffer); @@ -427,7 +429,7 @@ pub const ArrayBuffer = extern struct { return out; } - extern "C" fn JSArrayBuffer__fromDefaultAllocator(*JSC.JSGlobalObject, ptr: [*]u8, len: usize) JSC.JSValue; + extern "c" fn JSArrayBuffer__fromDefaultAllocator(*JSC.JSGlobalObject, ptr: [*]u8, len: usize) JSC.JSValue; pub fn toJSFromDefaultAllocator(globalThis: *JSC.JSGlobalObject, bytes: []u8) JSC.JSValue { return JSArrayBuffer__fromDefaultAllocator(globalThis, bytes.ptr, bytes.len); } @@ -652,7 +654,7 @@ pub const MarkedArrayBuffer = struct { } pub fn toNodeBuffer(this: *const MarkedArrayBuffer, ctx: js.JSContextRef) JSC.JSValue { - return JSValue.createBufferWithCtx(ctx, this.buffer.byteSlice(), this.buffer.ptr, MarkedArrayBuffer_deallocator); + return JSC.JSValue.createBufferWithCtx(ctx, this.buffer.byteSlice(), this.buffer.ptr, MarkedArrayBuffer_deallocator); } pub fn toJSObjectRef(this: *const MarkedArrayBuffer, ctx: js.JSContextRef, exception: js.ExceptionRef) js.JSObjectRef { @@ -711,7 +713,7 @@ pub const RefString = struct { pub const Hash = u32; pub const Map = std.HashMap(Hash, *JSC.RefString, IdentityContext(Hash), 80); - pub fn toJS(this: *RefString, global: *JSC.JSGlobalObject) JSValue { + pub fn toJS(this: *RefString, global: *JSC.JSGlobalObject) JSC.JSValue { return bun.String.init(this.impl).toJS(global); } @@ -783,9 +785,9 @@ const Expect = Test.Expect; const DescribeScope = Test.DescribeScope; const TestScope = Test.TestScope; const NodeFS = JSC.Node.NodeFS; -const TextEncoder = WebCore.TextEncoder; -const TextDecoder = WebCore.TextDecoder; -const TextEncoderStreamEncoder = WebCore.TextEncoderStreamEncoder; +const TextEncoder = JSC.WebCore.TextEncoder; +const TextDecoder = JSC.WebCore.TextDecoder; +const TextEncoderStreamEncoder = JSC.WebCore.TextEncoderStreamEncoder; const HTMLRewriter = JSC.Cloudflare.HTMLRewriter; const Element = JSC.Cloudflare.Element; const Comment = JSC.Cloudflare.Comment; @@ -902,7 +904,7 @@ pub const DOMEffect = struct { }; fn DOMCallArgumentType(comptime Type: type) []const u8 { - const ChildType = if (@typeInfo(Type) == .Pointer) std.meta.Child(Type) else Type; + const ChildType = if (@typeInfo(Type) == .pointer) std.meta.Child(Type) else Type; return switch (ChildType) { i8, u8, i16, u16, i32 => "JSC::SpecInt32Only", u32, i64, u64 => "JSC::SpecInt52Any", @@ -915,7 +917,7 @@ fn DOMCallArgumentType(comptime Type: type) []const u8 { } fn DOMCallArgumentTypeWrapper(comptime Type: type) []const u8 { - const ChildType = if (@typeInfo(Type) == .Pointer) std.meta.Child(Type) else Type; + const ChildType = if (@typeInfo(Type) == .pointer) std.meta.Child(Type) else Type; return switch (ChildType) { i32 => "int32_t", f64 => "double", @@ -929,7 +931,7 @@ fn DOMCallArgumentTypeWrapper(comptime Type: type) []const u8 { } fn DOMCallResultType(comptime Type: type) []const u8 { - const ChildType = if (@typeInfo(Type) == .Pointer) std.meta.Child(Type) else Type; + const ChildType = if (@typeInfo(Type) == .pointer) std.meta.Child(Type) else Type; return switch (ChildType) { i32 => "JSC::SpecInt32Only", bool => "JSC::SpecBoolean", @@ -963,7 +965,7 @@ pub fn DOMCall( thisValue: JSC.JSValue, arguments_ptr: [*]const JSC.JSValue, arguments_len: usize, - ) callconv(JSC.conv) JSValue { + ) callconv(JSC.conv) JSC.JSValue { return JSC.toJSHostValue(globalObject, @field(Container, functionName)(globalObject, thisValue, arguments_ptr[0..arguments_len])); } @@ -971,7 +973,7 @@ pub fn DOMCall( pub const Fastpath = @TypeOf(fastpath); pub const Arguments = std.meta.ArgsTuple(Fastpath); - pub fn put(globalObject: *JSC.JSGlobalObject, value: JSValue) void { + pub fn put(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { shim.cppFn("put", .{ globalObject, value }); } @@ -980,10 +982,8 @@ pub fn DOMCall( pub const Extern = [_][]const u8{"put"}; comptime { - if (!JSC.is_bindgen) { - @export(slowpath, .{ .name = shim.symbolName("slowpath") }); - @export(fastpath, .{ .name = shim.symbolName("fastpath") }); - } + @export(&slowpath, .{ .name = shim.symbolName("slowpath") }); + @export(&fastpath, .{ .name = shim.symbolName("fastpath") }); } }; } @@ -999,7 +999,7 @@ pub fn wrapInstanceMethod( ) InstanceMethodType(Container) { return struct { const FunctionType = @TypeOf(@field(Container, name)); - const FunctionTypeInfo: std.builtin.Type.Fn = @typeInfo(FunctionType).Fn; + const FunctionTypeInfo: std.builtin.Type.Fn = @typeInfo(FunctionType).@"fn"; const Args = std.meta.ArgsTuple(FunctionType); const eater = if (auto_protect) JSC.Node.ArgumentsSlice.protectEatNext else JSC.Node.ArgumentsSlice.nextEat; @@ -1081,7 +1081,7 @@ pub fn wrapInstanceMethod( args[i] = null; } }, - ZigString => { + JSC.ZigString => { var string_value = eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing argument", .{}); @@ -1103,32 +1103,32 @@ pub fn wrapInstanceMethod( args[i] = null; } }, - *Response => { + *JSC.WebCore.Response => { args[i] = (eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing Response object", .{}); - }).as(Response) orelse { + }).as(JSC.WebCore.Response) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Expected Response object", .{}); }; }, - *Request => { + *JSC.WebCore.Request => { args[i] = (eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing Request object", .{}); - }).as(Request) orelse { + }).as(JSC.WebCore.Request) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Expected Request object", .{}); }; }, - JSValue => { + JSC.JSValue => { const val = eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing argument", .{}); }; args[i] = val; }, - ?JSValue => { + ?JSC.JSValue => { args[i] = eater(&iter); }, JSC.C.ExceptionRef => { @@ -1160,7 +1160,7 @@ pub fn wrapStaticMethod( ) JSC.JSHostZigFunction { return struct { const FunctionType = @TypeOf(@field(Container, name)); - const FunctionTypeInfo: std.builtin.Type.Fn = @typeInfo(FunctionType).Fn; + const FunctionTypeInfo: std.builtin.Type.Fn = @typeInfo(FunctionType).@"fn"; const Args = std.meta.ArgsTuple(FunctionType); const eater = if (auto_protect) JSC.Node.ArgumentsSlice.protectEatNext else JSC.Node.ArgumentsSlice.nextEat; @@ -1234,7 +1234,7 @@ pub fn wrapStaticMethod( args[i] = null; } }, - ZigString => { + JSC.ZigString => { var string_value = eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing argument", .{}); @@ -1256,32 +1256,32 @@ pub fn wrapStaticMethod( args[i] = null; } }, - *Response => { + *JSC.WebCore.Response => { args[i] = (eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing Response object", .{}); - }).as(Response) orelse { + }).as(JSC.WebCore.Response) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Expected Response object", .{}); }; }, - *Request => { + *JSC.WebCore.Request => { args[i] = (eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing Request object", .{}); - }).as(Request) orelse { + }).as(JSC.WebCore.Request) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Expected Request object", .{}); }; }, - JSValue => { + JSC.WebCore.JSValue => { const val = eater(&iter) orelse { iter.deinit(); return globalThis.throwInvalidArguments("Missing argument", .{}); }; args[i] = val; }, - ?JSValue => { + ?JSC.WebCore.JSValue => { args[i] = eater(&iter); }, else => @compileError(std.fmt.comptimePrint("Unexpected Type " ++ @typeName(ArgType) ++ " at argument {d} in {s}#{s}", .{ i, @typeName(Container), name })), @@ -1392,7 +1392,7 @@ pub const BinaryType = enum(u4) { return Map.get(input); } - pub fn fromJSValue(globalThis: *JSC.JSGlobalObject, input: JSValue) bun.JSError!?BinaryType { + pub fn fromJSValue(globalThis: *JSC.JSGlobalObject, input: JSC.JSValue) bun.JSError!?BinaryType { if (input.isString()) { return Map.getWithEql(try input.toBunString2(globalThis), bun.String.eqlComptime); } @@ -1401,7 +1401,7 @@ pub const BinaryType = enum(u4) { } /// This clones bytes - pub fn toJS(this: BinaryType, bytes: []const u8, globalThis: *JSC.JSGlobalObject) JSValue { + pub fn toJS(this: BinaryType, bytes: []const u8, globalThis: *JSC.JSGlobalObject) JSC.JSValue { switch (this) { .Buffer => return JSC.ArrayBuffer.createBuffer(globalThis, bytes), .ArrayBuffer => return JSC.ArrayBuffer.create(globalThis, bytes, .ArrayBuffer), diff --git a/src/bun.js/bindings/AsyncContextFrame.cpp b/src/bun.js/bindings/AsyncContextFrame.cpp index 574f311a7bf314..e61b70da050416 100644 --- a/src/bun.js/bindings/AsyncContextFrame.cpp +++ b/src/bun.js/bindings/AsyncContextFrame.cpp @@ -44,7 +44,7 @@ JSValue AsyncContextFrame::withAsyncContextIfNeeded(JSGlobalObject* globalObject } // Construct a low-overhead wrapper - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); return AsyncContextFrame::create( vm, jsCast(globalObject)->AsyncContextFrameStructure(), diff --git a/src/bun.js/bindings/BunCommonStrings.cpp b/src/bun.js/bindings/BunCommonStrings.cpp index 6cbeefaf53731c..a0ed5922addcdd 100644 --- a/src/bun.js/bindings/BunCommonStrings.cpp +++ b/src/bun.js/bindings/BunCommonStrings.cpp @@ -20,13 +20,14 @@ using namespace JSC; init.set(jsOwnedString(init.vm, name.string())); \ }); -#define BUN_COMMON_STRINGS_LAZY_PROPERTY_DEFINITION_NOT_BUILTIN_NAMES(jsName) \ - this->m_commonString_##jsName.initLater( \ - [](const JSC::LazyProperty::Initializer& init) { \ - init.set(jsOwnedString(init.vm, #jsName##_s)); \ +#define BUN_COMMON_STRINGS_LAZY_PROPERTY_DEFINITION_NOT_BUILTIN_NAMES(methodName, stringLiteral) \ + this->m_commonString_##methodName.initLater( \ + [](const JSC::LazyProperty::Initializer& init) { \ + init.set(jsOwnedString(init.vm, stringLiteral##_s)); \ }); #define BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR(name) this->m_commonString_##name.visit(visitor); +#define BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR_NOT_BUILTIN_NAMES(name, literal) this->m_commonString_##name.visit(visitor); void CommonStrings::initialize() { @@ -38,7 +39,7 @@ template void CommonStrings::visit(Visitor& visitor) { BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR) - BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR) + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR_NOT_BUILTIN_NAMES) } template void CommonStrings::visit(JSC::AbstractSlotVisitor&); diff --git a/src/bun.js/bindings/BunCommonStrings.h b/src/bun.js/bindings/BunCommonStrings.h index 4e772840e6839c..2d94453465b3ec 100644 --- a/src/bun.js/bindings/BunCommonStrings.h +++ b/src/bun.js/bindings/BunCommonStrings.h @@ -11,17 +11,23 @@ // These ones don't need to be in BunBuiltinNames.h // If we don't use it as an identifier name, but we want to avoid allocating the string frequently, put it in this list. #define BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(macro) \ - macro(SystemError) \ - macro(S3Error) \ - macro(utf8) \ - macro(ucs2) \ - macro(utf16le) \ - macro(latin1) \ - macro(ascii) \ - macro(base64) \ - macro(base64url) \ - macro(hex) \ - macro(buffer) + macro(systemError, "SystemError") \ + macro(s3Error, "S3Error") \ + macro(utf8, "utf8") \ + macro(ucs2, "ucs2") \ + macro(utf16le, "utf16le") \ + macro(latin1, "latin1") \ + macro(ascii, "ascii") \ + macro(base64, "base64") \ + macro(base64url, "base64url") \ + macro(hex, "hex") \ + macro(buffer, "buffer") \ + macro(rsa, "rsa") \ + macro(rsaPss, "rsa-pss") \ + macro(ec, "ec") \ + macro(x25519, "x25519") \ + macro(ed25519, "ed25519") + // clang-format on #define BUN_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \ @@ -30,15 +36,21 @@ return m_commonString_##name.getInitializedOnMainThread(globalObject); \ } +#define BUN_COMMON_STRINGS_ACCESSOR_DEFINITION_NOT_BUILTIN_NAMES(name, literal) \ + BUN_COMMON_STRINGS_ACCESSOR_DEFINITION(name) + #define BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION(name) \ JSC::LazyProperty m_commonString_##name; +#define BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION_NOT_BUILTIN_NAMES(name, literal) \ + BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION(name) + namespace Bun { class CommonStrings { public: BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_ACCESSOR_DEFINITION) - BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_ACCESSOR_DEFINITION) + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_ACCESSOR_DEFINITION_NOT_BUILTIN_NAMES) void initialize(); template @@ -46,10 +58,12 @@ class CommonStrings { private: BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION) - BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION) + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION_NOT_BUILTIN_NAMES) }; } // namespace Bun #undef BUN_COMMON_STRINGS_ACCESSOR_DEFINITION #undef BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION +#undef BUN_COMMON_STRINGS_ACCESSOR_DEFINITION_NOT_BUILTIN_NAMES +#undef BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION_NOT_BUILTIN_NAMES diff --git a/src/bun.js/bindings/BunDebugger.cpp b/src/bun.js/bindings/BunDebugger.cpp index c0aeba45eb5447..5b0d930ce4feac 100644 --- a/src/bun.js/bindings/BunDebugger.cpp +++ b/src/bun.js/bindings/BunDebugger.cpp @@ -550,7 +550,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionCreateConnection, (JSGlobalObject * globalObj if (!targetContext || !onMessageFn) return JSValue::encode(jsUndefined()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto connection = BunInspectorConnection::create( *targetContext, targetContext->jsGlobalObject(), shouldRef); diff --git a/src/bun.js/bindings/BunJSCEventLoop.cpp b/src/bun.js/bindings/BunJSCEventLoop.cpp index 30498f1be9157e..6ca417034c3fc9 100644 --- a/src/bun.js/bindings/BunJSCEventLoop.cpp +++ b/src/bun.js/bindings/BunJSCEventLoop.cpp @@ -1,23 +1,33 @@ #include "root.h" +#include "BunClientData.h" #include #include -extern "C" int Bun__JSC_onBeforeWait(JSC::VM* vm) +// 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) { - UNUSED_PARAM(vm); - // TODO: use JSC timers, run the incremental sweeper. - // That will fix this. - // In the meantime, we're disabling this due to https://github.com/oven-sh/bun/issues/14982 - // if (vm->heap.hasAccess()) { - // vm->heap.releaseAccess(); - // return 1; - // } - return 0; + ASSERT(!drop_all_locks.has_value()); + if (vm) { + bool previouslyHadAccess = vm->heap.hasHeapAccess(); + drop_all_locks.emplace(*vm); + if (previouslyHadAccess) { + vm->heap.releaseAccess(); + } + } } extern "C" void Bun__JSC_onAfterWait(JSC::VM* vm) { - UNUSED_PARAM(vm); - // vm->heap.acquireAccess(); + if (vm) { + vm->heap.acquireAccess(); + drop_all_locks.reset(); + } } diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 8290a280d35910..640e901799902f 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -1,3 +1,4 @@ + #include "root.h" #include "JavaScriptCore/HeapProfiler.h" @@ -37,6 +38,7 @@ #include "ErrorCode.h" #include "GeneratedBunObject.h" #include "JavaScriptCore/BunV8HeapSnapshotBuilder.h" +#include "BunObjectModule.h" #ifdef WIN32 #include @@ -67,11 +69,12 @@ BUN_DECLARE_HOST_FUNCTION(Bun__DNSResolver__cancel); BUN_DECLARE_HOST_FUNCTION(Bun__fetch); BUN_DECLARE_HOST_FUNCTION(Bun__fetchPreconnect); BUN_DECLARE_HOST_FUNCTION(Bun__randomUUIDv7); -namespace Bun { using namespace JSC; using namespace WebCore; +namespace Bun { + extern "C" bool has_bun_garbage_collector_flag_enabled; static JSValue BunObject_getter_wrap_ArrayBufferSink(VM& vm, JSObject* bunObject) @@ -86,7 +89,7 @@ static JSValue constructEnvObject(VM& vm, JSObject* object) static inline JSC::EncodedJSValue flattenArrayOfBuffersIntoArrayBufferOrUint8Array(JSGlobalObject* lexicalGlobalObject, JSValue arrayValue, size_t maxLength, bool asUint8Array) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); if (arrayValue.isUndefinedOrNull() || !arrayValue) { return JSC::JSValue::encode(JSC::JSArrayBuffer::create(vm, lexicalGlobalObject->arrayBufferStructure(), JSC::ArrayBuffer::create(static_cast(0), 1))); @@ -228,7 +231,7 @@ static inline JSC::EncodedJSValue flattenArrayOfBuffersIntoArrayBufferOrUint8Arr JSC_DEFINE_HOST_FUNCTION(functionConcatTypedArrays, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(callFrame->argumentCount() < 1)) { @@ -422,7 +425,7 @@ static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(functionBunEscapeHTMLWitho JSC_DEFINE_HOST_FUNCTION(functionBunSleep, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue millisecondsValue = callFrame->argument(0); @@ -448,7 +451,7 @@ extern "C" JSC::EncodedJSValue Bun__escapeHTML16(JSGlobalObject* globalObject, J JSC_DEFINE_HOST_FUNCTION(functionBunEscapeHTML, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); JSC::JSValue argument = callFrame->argument(0); if (argument.isEmpty()) return JSValue::encode(jsEmptyString(vm)); @@ -477,7 +480,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBunEscapeHTML, (JSC::JSGlobalObject * lexicalGl JSC_DEFINE_HOST_FUNCTION(functionBunDeepEquals, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto* global = reinterpret_cast(globalObject); - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_THROW_SCOPE(vm); @@ -509,7 +512,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepEquals, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(functionBunDeepMatch, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { auto* global = reinterpret_cast(globalObject); - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_THROW_SCOPE(vm); @@ -550,20 +553,26 @@ JSC_DEFINE_HOST_FUNCTION(functionPathToFileURL, (JSC::JSGlobalObject * lexicalGl auto throwScope = DECLARE_THROW_SCOPE(vm); auto pathValue = callFrame->argument(0); - WTF::String pathString = pathValue.toWTFString(lexicalGlobalObject); - RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode({})); + JSValue jsValue; - pathString = pathResolveWTFString(lexicalGlobalObject, pathString); + { + WTF::String pathString = pathValue.toWTFString(lexicalGlobalObject); + RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode({})); + pathString = pathResolveWTFString(lexicalGlobalObject, pathString); - auto fileURL = WTF::URL::fileURLWithFileSystemPath(pathString); - auto object = WebCore::DOMURL::create(fileURL.string(), String()); - auto jsValue = WebCore::toJSNewlyCreated>(*lexicalGlobalObject, globalObject, throwScope, WTFMove(object)); + auto fileURL = WTF::URL::fileURLWithFileSystemPath(pathString); + auto object = WebCore::DOMURL::create(fileURL.string(), String()); + jsValue = WebCore::toJSNewlyCreated>(*lexicalGlobalObject, globalObject, throwScope, WTFMove(object)); + } + + auto* jsDOMURL = jsCast(jsValue.asCell()); + vm.heap.reportExtraMemoryAllocated(jsDOMURL, jsDOMURL->wrapped().memoryCostForGC()); RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(jsValue)); } JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshot, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); vm.ensureHeapProfiler(); auto& heapProfiler = *vm.heapProfiler(); heapProfiler.clearSnapshots(); @@ -602,7 +611,7 @@ JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshot, (JSC::JSGlobalObject * gl JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue arg0 = callFrame->argument(0); WTF::URL url; @@ -646,28 +655,19 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj #endif // ban url-encoded slashes. '/' on posix, '/' and '\' on windows. - StringView p = url.path(); - if (p.length() > 3) { - for (int i = 0; i < p.length() - 2; i++) { - if (p[i] == '%') { - const char second = p[i + 1]; - const uint8_t third = p[i + 2] | 0x20; + const StringView p = url.path(); + if (p.contains('%')) { #if OS(WINDOWS) - if ( - (second == '2' && third == 102) || // 2f 2F '/' - (second == '5' && third == 99) // 5c 5C '\' - ) { - Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded \\ or / characters"_s); - return {}; - } + if (p.contains("%2f"_s) || p.contains("%5c"_s) || p.contains("%2F"_s) || p.contains("%5C"_s)) { + Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded \\ or / characters"_s); + return {}; + } #else - if (second == '2' && third == 102) { - Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded / characters"_s); - return {}; - } -#endif - } + if (p.contains("%2f"_s) || p.contains("%2F"_s)) { + Bun::ERR::INVALID_FILE_URL_PATH(scope, globalObject, "must not include encoded / characters"_s); + return {}; } +#endif } auto fileSystemPath = url.fileSystemPath(); @@ -731,13 +731,13 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj isMainThread constructIsMainThread ReadOnly|DontDelete|PropertyCallback jest BunObject_callback_jest DontEnum|DontDelete|Function 1 listen BunObject_callback_listen DontDelete|Function 1 - udpSocket BunObject_callback_udpSocket DontDelete|Function 1 + udpSocket BunObject_callback_udpSocket DontDelete|Function 1 main BunObject_getter_wrap_main DontDelete|PropertyCallback mmap BunObject_callback_mmap DontDelete|Function 1 nanoseconds functionBunNanoseconds DontDelete|Function 0 openInEditor BunObject_callback_openInEditor DontDelete|Function 1 - origin BunObject_getter_wrap_origin DontDelete|PropertyCallback - version_with_sha constructBunVersionWithSha ReadOnly|DontDelete|PropertyCallback + origin BunObject_getter_wrap_origin DontEnum|ReadOnly|DontDelete|PropertyCallback + version_with_sha constructBunVersionWithSha DontEnum|ReadOnly|DontDelete|PropertyCallback password constructPasswordObject DontDelete|PropertyCallback pathToFileURL functionPathToFileURL DontDelete|Function 1 peek constructBunPeekObject DontDelete|PropertyCallback @@ -841,4 +841,54 @@ JSC::JSObject* createBunObject(VM& vm, JSObject* globalObject) return JSBunObject::create(vm, jsCast(globalObject)); } +static void exportBunObject(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) +{ + exportNames.reserveCapacity(std::size(bunObjectTableValues) + 1); + exportValues.ensureCapacity(std::size(bunObjectTableValues) + 1); + + PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + auto scope = DECLARE_THROW_SCOPE(vm); + object->getOwnNonIndexPropertyNames(globalObject, propertyNames, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(scope, void()); + + for (const auto& propertyName : propertyNames) { + exportNames.append(propertyName); + auto catchScope = DECLARE_CATCH_SCOPE(vm); + + // Yes, we have to call getters :( + JSValue value = object->get(globalObject, propertyName); + + if (catchScope.exception()) { + catchScope.clearException(); + value = jsUndefined(); + } + exportValues.append(value); + } + + exportNames.append(vm.propertyNames->defaultKeyword); + exportValues.append(object); +} + +} + +namespace Zig { +void generateNativeModule_BunObject(JSC::JSGlobalObject* lexicalGlobalObject, + JSC::Identifier moduleKey, + Vector& exportNames, + JSC::MarkedArgumentBuffer& exportValues) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + Zig::GlobalObject* globalObject = jsCast(lexicalGlobalObject); + + auto scope = DECLARE_THROW_SCOPE(vm); + auto* object = globalObject->bunObject(); + + // :'( + object->reifyAllStaticProperties(lexicalGlobalObject); + + RETURN_IF_EXCEPTION(scope, void()); + + Bun::exportBunObject(vm, globalObject, object, exportNames, exportValues); +} + } diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index 1c183820685946..0b3d9ad2b254bd 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -47,7 +47,7 @@ static bool isValidNamespaceString(String& namespaceString) static JSC::EncodedJSValue jsFunctionAppendOnLoadPluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target, BunPlugin::Base& plugin, void* ctx, OnAppendPluginCallback callback) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callframe->argumentCount() < 2) { @@ -99,7 +99,7 @@ static JSC::EncodedJSValue jsFunctionAppendOnLoadPluginBody(JSC::JSGlobalObject* static EncodedJSValue jsFunctionAppendVirtualModulePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callframe->argumentCount() < 2) { @@ -155,7 +155,7 @@ static EncodedJSValue jsFunctionAppendVirtualModulePluginBody(JSC::JSGlobalObjec static JSC::EncodedJSValue jsFunctionAppendOnResolvePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target, BunPlugin::Base& plugin, void* ctx, OnAppendPluginCallback callback) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callframe->argumentCount() < 2) { @@ -262,7 +262,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBrowser, (JSC::JSGlobalO static inline JSC::EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (callframe->argumentCount() < 1) { JSC::throwTypeError(globalObject, throwScope, "plugin needs at least one argument (an object)"_s); @@ -445,7 +445,7 @@ Structure* JSModuleMock::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globa JSObject* JSModuleMock::executeOnce(JSC::JSGlobalObject* lexicalGlobalObject) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (hasCalledModuleMock) { @@ -484,7 +484,7 @@ extern "C" JSC::EncodedJSValue Bun__resolveSyncWithSource(JSC::JSGlobalObject* g BUN_DECLARE_HOST_FUNCTION(JSMock__jsModuleMock); extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); Zig::GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(!globalObject)) { @@ -704,7 +704,7 @@ EncodedJSValue BunPlugin::OnLoad::run(JSC::JSGlobalObject* globalObject, BunStri } JSC::MarkedArgumentBuffer arguments; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* paramsObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1); const auto& builtinNames = WebCore::builtinNames(vm); @@ -790,7 +790,7 @@ EncodedJSValue BunPlugin::OnResolve::run(JSC::JSGlobalObject* globalObject, BunS } JSC::MarkedArgumentBuffer arguments; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* paramsObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 2); const auto& builtinNames = WebCore::builtinNames(vm); @@ -880,7 +880,7 @@ JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specif WTF::String specifierString = specifier->toWTFString(BunString::ZeroCopy); if (auto virtualModuleFn = virtualModules.get(specifierString)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* function = virtualModuleFn.get(); auto throwScope = DECLARE_THROW_SCOPE(vm); diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 57812b1af331af..a3063b71420077 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -103,6 +103,7 @@ typedef int mode_t; extern "C" bool Bun__Node__ProcessNoDeprecation; extern "C" bool Bun__Node__ProcessThrowDeprecation; +extern "C" int32_t bun_stdio_tty[3]; namespace Bun { @@ -259,7 +260,7 @@ static void dispatchExitInternal(JSC::JSGlobalObject* globalObject, Process* pro return; processIsExiting = true; auto& emitter = process->wrapped(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (vm.hasTerminationRequest() || vm.hasExceptionsAfterHandlingTraps()) return; @@ -277,7 +278,7 @@ static void dispatchExitInternal(JSC::JSGlobalObject* globalObject, Process* pro JSC_DEFINE_CUSTOM_SETTER(Process_defaultSetter, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName propertyName)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* thisObject = JSC::jsDynamicCast(JSValue::decode(thisValue)); if (value) @@ -298,7 +299,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb Zig::GlobalObject* globalObject = reinterpret_cast(globalObject_); auto callCountAtStart = globalObject->napiModuleRegisterCallCount; auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto argCount = callFrame->argumentCount(); if (argCount < 2) { @@ -437,6 +438,13 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb EncodedJSValue exportsValue = JSC::JSValue::encode(exports); JSC::JSValue resultValue = JSValue::decode(napi_register_module_v1(globalObject, exportsValue)); + RETURN_IF_EXCEPTION(scope, {}); + // If a module returns `nullptr` (cast to a napi_value) from its register function, we should + // use the `exports` value (which may have had properties added to it) as the return value of + // `require()`. + if (resultValue.isEmpty()) { + resultValue = exports; + } if (auto resultObject = resultValue.getObject()) { #if OS(DARWIN) || OS(LINUX) @@ -453,11 +461,10 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, (JSC::JSGlobalObject * globalOb Bun::NapiExternal* napi_external = Bun::NapiExternal::create(vm, globalObject->NapiExternalStructure(), meta, nullptr, nullptr); bool success = resultObject->putDirect(vm, WebCore::builtinNames(vm).napiDlopenHandlePrivateName(), napi_external, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); ASSERT(success); + RETURN_IF_EXCEPTION(scope, {}); } } - RETURN_IF_EXCEPTION(scope, {}); - globalObject->m_pendingNapiModuleAndExports[0].clear(); globalObject->m_pendingNapiModuleAndExports[1].clear(); globalObject->m_pendingNapiModuleDlopenHandle = nullptr; @@ -480,7 +487,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUmask, (JSGlobalObject * globalObject, return JSValue::encode(jsNumber(currentMask)); } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -510,7 +517,7 @@ extern "C" void Process__dispatchOnBeforeExit(Zig::GlobalObject* globalObject, u if (!globalObject->hasProcessObject()) { return; } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* process = jsCast(globalObject->processObject()); MarkedArgumentBuffer arguments; arguments.append(jsNumber(exitCode)); @@ -545,7 +552,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUptime, (JSC::JSGlobalObject * lexicalG JSC_DEFINE_HOST_FUNCTION(Process_functionExit, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* zigGlobal = defaultGlobalObject(globalObject); auto process = jsCast(zigGlobal->processObject()); @@ -572,7 +579,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionExit, (JSC::JSGlobalObject * globalObje JSC_DEFINE_HOST_FUNCTION(Process_setUncaughtExceptionCaptureCallback, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { auto* globalObject = reinterpret_cast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto arg0 = callFrame->argument(0); auto process = jsCast(globalObject->processObject()); @@ -610,7 +617,7 @@ extern "C" uint64_t Bun__readOriginTimer(void*); JSC_DEFINE_HOST_FUNCTION(Process_functionHRTime, (JSC::JSGlobalObject * globalObject_, JSC::CallFrame* callFrame)) { Zig::GlobalObject* globalObject = reinterpret_cast(globalObject_); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); uint64_t time = Bun__readOriginTimer(globalObject->bunVM()); @@ -667,7 +674,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionHRTimeBigInt, (JSC::JSGlobalObject * gl JSC_DEFINE_HOST_FUNCTION(Process_functionChdir, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -884,7 +891,7 @@ extern "C" int Bun__handleUncaughtException(JSC::JSGlobalObject* lexicalGlobalOb auto* globalObject = jsCast(lexicalGlobalObject); auto* process = jsCast(globalObject->processObject()); auto& wrapped = process->wrapped(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); MarkedArgumentBuffer args; args.append(exception); @@ -1061,10 +1068,18 @@ static void onDidChangeListeners(EventEmitter& eventEmitter, const Identifier& e } if (auto signalNumber = signalNameToNumberMap->get(eventName.string())) { -#if !OS(WINDOWS) +#if OS(LINUX) + // SIGKILL and SIGSTOP cannot be handled, and JSC needs its own signal handler to + // suspend and resume the JS thread which we must not override. + if (signalNumber != SIGKILL && signalNumber != SIGSTOP && signalNumber != g_wtfConfig.sigThreadSuspendResume) { +#elif OS(DARWIN) + // these signals cannot be handled if (signalNumber != SIGKILL && signalNumber != SIGSTOP) { +#elif OS(WINDOWS) + // windows has no SIGSTOP + if (signalNumber != SIGKILL) { #else - if (signalNumber != SIGKILL) { // windows has no SIGSTOP +#error unknown OS #endif if (isAdded) { @@ -1126,7 +1141,7 @@ Process::~Process() JSC_DEFINE_HOST_FUNCTION(jsFunction_emitWarning, (JSC::JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto* globalObject = defaultGlobalObject(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* process = jsCast(globalObject->processObject()); auto value = callFrame->argument(0); @@ -1147,7 +1162,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_emitWarning, (JSC::JSGlobalObject * lexicalG JSC_DEFINE_HOST_FUNCTION(jsFunction_throwValue, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); scope.throwException(globalObject, value); @@ -1929,7 +1944,7 @@ static JSValue constructReportObjectComplete(VM& vm, Zig::GlobalObject* globalOb JSC_DEFINE_HOST_FUNCTION(Process_functionGetReport, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // TODO: node:vm return JSValue::encode(constructReportObjectComplete(vm, jsCast(globalObject), String())); @@ -1937,7 +1952,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionGetReport, (JSGlobalObject * globalObje JSC_DEFINE_HOST_FUNCTION(Process_functionWriteReport, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // TODO: return JSValue::encode(callFrame->argument(0)); @@ -2011,18 +2026,25 @@ static JSValue constructProcessHrtimeObject(VM& vm, JSObject* processObject) return hrtime; } +enum class BunProcessStdinFdType : int32_t { + file = 0, + pipe = 1, + socket = 2, +}; +extern "C" BunProcessStdinFdType Bun__Process__getStdinFdType(void*, int fd); -#if OS(WINDOWS) -extern "C" void Bun__ForceFileSinkToBeSynchronousOnWindows(JSC::JSGlobalObject*, JSC::EncodedJSValue); -#endif +extern "C" void Bun__ForceFileSinkToBeSynchronousForProcessObjectStdio(JSC::JSGlobalObject*, JSC::EncodedJSValue); static JSValue constructStdioWriteStream(JSC::JSGlobalObject* globalObject, int fd) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSFunction* getStdioWriteStream = JSC::JSFunction::create(vm, globalObject, processObjectInternalsGetStdioWriteStreamCodeGenerator(vm), globalObject); JSC::MarkedArgumentBuffer args; args.append(JSC::jsNumber(fd)); + args.append(jsBoolean(bun_stdio_tty[fd])); + BunProcessStdinFdType fdType = Bun__Process__getStdinFdType(Bun::vm(vm), fd); + args.append(jsNumber(static_cast(fdType))); JSC::CallData callData = JSC::getCallData(getStdioWriteStream); @@ -2042,15 +2064,26 @@ static JSValue constructStdioWriteStream(JSC::JSGlobalObject* globalObject, int ASSERT_WITH_MESSAGE(JSC::isJSArray(result), "Expected an array from getStdioWriteStream"); JSC::JSArray* resultObject = JSC::jsCast(result); + // process.stdout and process.stderr differ from other Node.js streams in important ways: + // 1. They are used internally by console.log() and console.error(), respectively. + // 2. Writes may be synchronous depending on what the stream is connected to and whether the system is Windows or POSIX: + // Files: synchronous on Windows and POSIX + // TTYs (Terminals): asynchronous on Windows, synchronous on POSIX + // Pipes (and sockets): synchronous on Windows, asynchronous on POSIX + bool forceSync = false; #if OS(WINDOWS) - Zig::GlobalObject* globalThis = jsCast(globalObject); - // Node.js docs - https://nodejs.org/api/process.html#a-note-on-process-io - // > Files: synchronous on Windows and POSIX - // > TTYs (Terminals): asynchronous on Windows, synchronous on POSIX - // > Pipes (and sockets): synchronous on Windows, asynchronous on POSIX - // > Synchronous writes avoid problems such as output written with console.log() or console.error() being unexpectedly interleaved, or not written at all if process.exit() is called before an asynchronous write completes. See process.exit() for more information. - Bun__ForceFileSinkToBeSynchronousOnWindows(globalThis, JSValue::encode(resultObject->getIndex(globalObject, 1))); + forceSync = fdType == BunProcessStdinFdType::file || fdType == BunProcessStdinFdType::pipe; +#else + // Note: files are always sync anyway. + // forceSync = fdType == BunProcessStdinFdType::file || bun_stdio_tty[fd]; + + // TDOO: once console.* is wired up to write/read through the same buffering mechanism as FileSink for process.stdout, process.stderr, we can make this non-blocking for sockets on POSIX. + // Until then, we have to force it to be sync EVEN for sockets or else console.log() may flush at a different time than process.stdout.write. + forceSync = true; #endif + if (forceSync) { + Bun__ForceFileSinkToBeSynchronousForProcessObjectStdio(globalObject, JSValue::encode(resultObject->getIndex(globalObject, 1))); + } return resultObject->getIndex(globalObject, 0); } @@ -2076,7 +2109,9 @@ static JSValue constructStdin(VM& vm, JSObject* processObject) JSC::JSFunction* getStdioWriteStream = JSC::JSFunction::create(vm, globalObject, processObjectInternalsGetStdinStreamCodeGenerator(vm), globalObject); JSC::MarkedArgumentBuffer args; args.append(JSC::jsNumber(STDIN_FILENO)); - + args.append(jsBoolean(bun_stdio_tty[STDIN_FILENO])); + BunProcessStdinFdType fdType = Bun__Process__getStdinFdType(Bun::vm(vm), STDIN_FILENO); + args.append(jsNumber(static_cast(fdType))); JSC::CallData callData = JSC::getCallData(getStdioWriteStream); NakedPtr returnedException = nullptr; @@ -2123,7 +2158,7 @@ JSC_DEFINE_HOST_FUNCTION(processDisonnectFinish, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(Bun__Process__disconnect, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto global = jsCast(globalObject); if (!Bun__GlobalObject__hasIPC(globalObject)) { @@ -2152,7 +2187,7 @@ static JSValue constructProcessChannel(VM& vm, JSObject* processObject) { auto* globalObject = processObject->globalObject(); if (Bun__GlobalObject__hasIPC(globalObject)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSFunction* getControl = JSC::JSFunction::create(vm, globalObject, processObjectInternalsGetChannelCodeGenerator(vm), globalObject); @@ -2270,7 +2305,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functiongetgid, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(Process_functiongetgroups, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); int ngroups = getgroups(0, nullptr); auto throwScope = DECLARE_THROW_SCOPE(vm); if (ngroups == -1) { @@ -2340,7 +2375,7 @@ static JSValue maybe_gid_by_name(JSC::ThrowScope& throwScope, JSGlobalObject* gl JSC_DEFINE_HOST_FUNCTION(Process_functionsetuid, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); auto is_number = value.isNumber(); @@ -2358,7 +2393,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionsetuid, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(Process_functionseteuid, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); auto is_number = value.isNumber(); @@ -2376,7 +2411,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionseteuid, (JSGlobalObject * globalObject JSC_DEFINE_HOST_FUNCTION(Process_functionsetegid, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); auto is_number = value.isNumber(); @@ -2394,7 +2429,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionsetegid, (JSGlobalObject * globalObject JSC_DEFINE_HOST_FUNCTION(Process_functionsetgid, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); auto is_number = value.isNumber(); @@ -2412,7 +2447,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionsetgid, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(Process_functionsetgroups, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto groups = callFrame->argument(0); Bun::V::validateArray(scope, globalObject, groups, "groups"_s, jsUndefined()); @@ -2450,7 +2485,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionsetgroups, (JSGlobalObject * globalObje JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSValue arg0 = callFrame->argument(0); @@ -2516,7 +2551,7 @@ inline JSValue processBindingConfig(Zig::GlobalObject* globalObject, JSC::VM& vm JSValue createCryptoX509Object(JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto cryptoX509 = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1); cryptoX509->putDirect(vm, JSC::Identifier::fromString(vm, "isX509Certificate"_s), JSC::JSFunction::create(vm, globalObject, 1, String("isX509Certificate"_s), jsIsX509Certificate, ImplementationVisibility::Public), 0); @@ -2530,10 +2565,11 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObje auto globalObject = jsCast(jsGlobalObject); auto process = jsCast(globalObject->processObject()); auto moduleName = callFrame->argument(0).toWTFString(globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); // clang-format off if (moduleName == "async_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("async_wrap"); - if (moduleName == "buffer"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("buffer", "2020"); + if (moduleName == "buffer"_s) return JSValue::encode(globalObject->processBindingBuffer()); if (moduleName == "cares_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("cares_wrap"); if (moduleName == "config"_s) return JSValue::encode(processBindingConfig(globalObject, vm)); if (moduleName == "constants"_s) return JSValue::encode(globalObject->processBindingConstants()); @@ -2570,7 +2606,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObje JSC_DEFINE_HOST_FUNCTION(Process_functionReallyExit, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); uint8_t exitCode = 0; JSValue arg0 = callFrame->argument(0); @@ -2654,7 +2690,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionConstrainedMemory, (JSC::JSGlobalObject JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); #if !OS(WINDOWS) struct rusage rusage; @@ -2821,7 +2857,7 @@ int getRSS(size_t* rss) JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsage, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* process = getProcessObject(globalObject, callFrame->thisValue()); @@ -2872,7 +2908,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsage, (JSC::JSGlobalObject * glo JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsageRSS, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); size_t current_rss = 0; @@ -2886,7 +2922,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsageRSS, (JSC::JSGlobalObject * JSC_DEFINE_HOST_FUNCTION(Process_functionOpenStdin, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); Zig::GlobalObject* global = defaultGlobalObject(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -3004,7 +3040,7 @@ void Process::queueNextTick(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSVa extern "C" void Bun__Process__queueNextTick1(GlobalObject* globalObject, EncodedJSValue value, EncodedJSValue arg1) { auto process = jsCast(globalObject->processObject()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); process->queueNextTick(vm, globalObject, JSValue::decode(value), JSValue::decode(arg1)); } JSC_DECLARE_HOST_FUNCTION(Bun__Process__queueNextTick1); @@ -3102,7 +3138,7 @@ JSC_DEFINE_CUSTOM_GETTER(processDebugPort, (JSC::JSGlobalObject * globalObject, JSC_DEFINE_CUSTOM_SETTER(setProcessDebugPort, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, JSC::PropertyName)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue value = JSValue::decode(encodedValue); @@ -3131,7 +3167,7 @@ JSC_DEFINE_CUSTOM_GETTER(processTitle, (JSC::JSGlobalObject * globalObject, JSC: Bun__Process__getTitle(globalObject, &str); return JSValue::encode(Zig::toJSStringValue(str, globalObject)); #else - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); char title[1024]; if (uv_get_process_title(title, sizeof(title)) != 0) { return JSValue::encode(jsString(vm, String("bun"_s))); @@ -3143,7 +3179,7 @@ JSC_DEFINE_CUSTOM_GETTER(processTitle, (JSC::JSGlobalObject * globalObject, JSC: JSC_DEFINE_CUSTOM_SETTER(setProcessTitle, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSObject* thisObject = JSC::jsDynamicCast(JSValue::decode(thisValue)); JSC::JSString* jsString = JSC::jsDynamicCast(JSValue::decode(value)); @@ -3164,7 +3200,7 @@ JSC_DEFINE_CUSTOM_SETTER(setProcessTitle, (JSC::JSGlobalObject * globalObject, J static inline JSValue getCachedCwd(JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/lib/internal/bootstrap/switches/does_own_process_state.js#L142-L146 diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 0657074dd5501a..b8e3bb9a869c12 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -96,19 +96,13 @@ extern "C" BunString BunString__tryCreateAtom(const char* bytes, size_t length) extern "C" JSC::EncodedJSValue BunString__createUTF8ForJS(JSC::JSGlobalObject* globalObject, const char* ptr, size_t length) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); + if (length == 0) { + return JSValue::encode(jsEmptyString(vm)); + } if (simdutf::validate_ascii(ptr, length)) { - std::span destination; - - auto impl = WTF::StringImpl::tryCreateUninitialized(length, destination); - if (UNLIKELY(!impl)) { - throwOutOfMemoryError(globalObject, scope); - return JSC::EncodedJSValue(); - } - std::span source = { reinterpret_cast(ptr), length }; - WTF::memcpySpan(destination, source); - return JSValue::encode(jsString(vm, String(WTFMove(impl)))); + return JSValue::encode(jsString(vm, WTF::String(std::span(reinterpret_cast(ptr), length)))); } auto str = WTF::String::fromUTF8ReplacingInvalidSequences(std::span { reinterpret_cast(ptr), length }); @@ -116,12 +110,12 @@ extern "C" JSC::EncodedJSValue BunString__createUTF8ForJS(JSC::JSGlobalObject* g throwOutOfMemoryError(globalObject, scope); return JSC::EncodedJSValue(); } - return JSValue::encode(jsString(vm, str)); + return JSValue::encode(jsString(vm, WTFMove(str))); } extern "C" JSC::EncodedJSValue BunString__transferToJS(BunString* bunString, JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(bunString->tag == BunStringTag::Empty || bunString->tag == BunStringTag::Dead)) { @@ -129,7 +123,15 @@ extern "C" JSC::EncodedJSValue BunString__transferToJS(BunString* bunString, JSC } if (LIKELY(bunString->tag == BunStringTag::WTFStringImpl)) { +#if ASSERT_ENABLED + unsigned refCount = bunString->impl.wtf->refCount(); + ASSERT(refCount > 0 && !bunString->impl.wtf->isEmpty()); +#endif auto str = bunString->toWTFString(); +#if ASSERT_ENABLED + unsigned newRefCount = bunString->impl.wtf->refCount(); + ASSERT(newRefCount == refCount + 1); +#endif bunString->impl.wtf->deref(); *bunString = { .tag = BunStringTag::Dead }; return JSValue::encode(jsString(vm, WTFMove(str))); @@ -326,7 +328,6 @@ extern "C" BunString BunString__fromUTF8(const char* bytes, size_t length) return { .tag = BunStringTag::Dead }; } RELEASE_ASSERT(simdutf::convert_utf8_to_utf16(bytes, length, ptr.data()) == u16Length); - impl->ref(); return { BunStringTag::WTFStringImpl, { .wtf = impl.leakRef() } }; } @@ -334,8 +335,8 @@ extern "C" BunString BunString__fromUTF8(const char* bytes, size_t length) if (UNLIKELY(str.isNull())) { return { .tag = BunStringTag::Dead }; } - str.impl()->ref(); - return Bun::toString(str); + auto impl = str.releaseImpl(); + return Bun::toString(impl.leakRef()); } extern "C" BunString BunString__fromLatin1(const char* bytes, size_t length) @@ -430,7 +431,7 @@ extern "C" JSC::EncodedJSValue BunString__createArray( if (length == 0) return JSValue::encode(JSC::constructEmptyArray(globalObject, nullptr)); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); // Using tryCreateUninitialized here breaks stuff.. @@ -450,18 +451,23 @@ extern "C" JSC::EncodedJSValue BunString__createArray( extern "C" void BunString__toWTFString(BunString* bunString) { + WTF::String str; if (bunString->tag == BunStringTag::ZigString) { if (Zig::isTaggedExternalPtr(bunString->impl.zig.ptr)) { - bunString->impl.wtf = Zig::toString(bunString->impl.zig).impl(); + str = Zig::toString(bunString->impl.zig); } else { - bunString->impl.wtf = Zig::toStringCopy(bunString->impl.zig).impl(); + str = Zig::toStringCopy(bunString->impl.zig); } - bunString->tag = BunStringTag::WTFStringImpl; } else if (bunString->tag == BunStringTag::StaticZigString) { - bunString->impl.wtf = Zig::toStringStatic(bunString->impl.zig).impl(); - bunString->tag = BunStringTag::WTFStringImpl; + str = Zig::toStringStatic(bunString->impl.zig); + } else { + return; } + + auto impl = str.releaseImpl(); + bunString->impl.wtf = impl.leakRef(); + bunString->tag = BunStringTag::WTFStringImpl; } extern "C" BunString URL__getFileURLString(BunString* filePath) @@ -479,6 +485,8 @@ extern "C" JSC__JSValue BunString__toJSDOMURL(JSC::JSGlobalObject* lexicalGlobal auto object = WebCore::DOMURL::create(str, String()); auto jsValue = WebCore::toJSNewlyCreated>(*lexicalGlobalObject, globalObject, throwScope, WTFMove(object)); + auto* jsDOMURL = jsCast(jsValue.asCell()); + vm.heap.reportExtraMemoryAllocated(jsDOMURL, jsDOMURL->wrapped().memoryCostForGC()); RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(jsValue)); } @@ -661,6 +669,34 @@ WTF::String BunString::toWTFString(ZeroCopyTag) const return WTF::String(); } +WTF::String BunString::transferToWTFString() +{ + if (this->tag == BunStringTag::ZigString) { + if (Zig::isTaggedUTF8Ptr(this->impl.zig.ptr)) { + auto str = Zig::toStringCopy(this->impl.zig); + *this = Zig::BunStringEmpty; + return str; + } else { + auto str = Zig::toString(this->impl.zig); + *this = Zig::BunStringEmpty; + return str; + } + } else if (this->tag == BunStringTag::StaticZigString) { + auto str = Zig::toStringStatic(this->impl.zig); + *this = Zig::BunStringEmpty; + return str; + } else if (this->tag == BunStringTag::WTFStringImpl) { + ASSERT(this->impl.wtf->refCount() > 0 && !this->impl.wtf->isEmpty()); + + auto str = WTF::String(this->impl.wtf); + this->impl.wtf->deref(); + *this = Zig::BunStringEmpty; + return str; + } + + return WTF::String(); +} + extern "C" BunString BunString__createExternalGloballyAllocatedLatin1( const LChar* bytes, size_t length) diff --git a/src/bun.js/bindings/CPUFeatures.zig b/src/bun.js/bindings/CPUFeatures.zig index a5f6f444912d76..76cb6b7d78816e 100644 --- a/src/bun.js/bindings/CPUFeatures.zig +++ b/src/bun.js/bindings/CPUFeatures.zig @@ -84,6 +84,6 @@ else } }; -extern "C" fn bun_cpu_features() u8; +extern "c" fn bun_cpu_features() u8; const assert = bun.debugAssert; diff --git a/src/bun.js/bindings/CallSite.cpp b/src/bun.js/bindings/CallSite.cpp index af78f9584a8970..ecc731dc632208 100644 --- a/src/bun.js/bindings/CallSite.cpp +++ b/src/bun.js/bindings/CallSite.cpp @@ -90,7 +90,7 @@ void CallSite::visitChildrenImpl(JSCell* cell, Visitor& visitor) } JSC_DEFINE_HOST_FUNCTION(nativeFrameForTesting, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSFunction* function = jsCast(callFrame->argument(0)); diff --git a/src/bun.js/bindings/CallSite.h b/src/bun.js/bindings/CallSite.h index 4c0d095c146322..31236d80b38962 100644 --- a/src/bun.js/bindings/CallSite.h +++ b/src/bun.js/bindings/CallSite.h @@ -43,7 +43,7 @@ class CallSite final : public JSC::JSNonFinalObject { static CallSite* create(JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCStackFrame& stackFrame, bool encounteredStrictFrame) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); CallSite* callSite = new (NotNull, JSC::allocateCell(vm)) CallSite(vm, structure); callSite->finishCreation(vm, globalObject, stackFrame, encounteredStrictFrame); return callSite; diff --git a/src/bun.js/bindings/CallSitePrototype.cpp b/src/bun.js/bindings/CallSitePrototype.cpp index ba7c8bdf07f6e7..4b767656708bf6 100644 --- a/src/bun.js/bindings/CallSitePrototype.cpp +++ b/src/bun.js/bindings/CallSitePrototype.cpp @@ -41,7 +41,7 @@ JSC_DECLARE_HOST_FUNCTION(callSiteProtoFuncToJSON); ALWAYS_INLINE static CallSite* getCallSite(JSGlobalObject* globalObject, JSC::JSValue thisValue) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (auto* callSite = JSC::jsDynamicCast(thisValue)) { @@ -53,7 +53,7 @@ ALWAYS_INLINE static CallSite* getCallSite(JSGlobalObject* globalObject, JSC::JS } #define ENTER_PROTO_FUNC() \ - JSC::VM& vm = globalObject->vm(); \ + auto& vm = JSC::getVM(globalObject); \ auto scope = DECLARE_THROW_SCOPE(vm); \ \ CallSite* callSite = getCallSite(globalObject, callFrame->thisValue()); \ diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index 5fb4cdb9d2d275..b2d67fd498fc86 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -232,7 +232,7 @@ bool JSCommonJSModule::load(JSC::VM& vm, Zig::GlobalObject* globalObject, WTF::N JSC_DEFINE_HOST_FUNCTION(jsFunctionLoadModule, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* globalObject = jsCast(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSCommonJSModule* moduleObject = jsDynamicCast(callframe->argument(0)); @@ -302,7 +302,7 @@ Structure* RequireResolveFunctionPrototype::createStructure( RequireResolveFunctionPrototype* RequireResolveFunctionPrototype::create(JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* structure = RequireResolveFunctionPrototype::createStructure(vm, globalObject); RequireResolveFunctionPrototype* prototype = new (NotNull, JSC::allocateCell(vm)) RequireResolveFunctionPrototype(vm, structure); @@ -313,7 +313,7 @@ RequireResolveFunctionPrototype* RequireResolveFunctionPrototype::create(JSC::JS RequireFunctionPrototype* RequireFunctionPrototype::create( JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* structure = RequireFunctionPrototype::createStructure(vm, globalObject); RequireFunctionPrototype* prototype = new (NotNull, JSC::allocateCell(vm)) RequireFunctionPrototype(vm, structure); @@ -527,7 +527,7 @@ JSC_DEFINE_HOST_FUNCTION(functionCommonJSModuleRecord_compile, (JSGlobalObject * return JSValue::encode(jsUndefined()); } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); String sourceString = callframe->argument(0).toWTFString(globalObject); @@ -658,7 +658,7 @@ void JSCommonJSModule::finishCreation(JSC::VM& vm, JSC::JSString* id, JSValue fi JSC::Structure* JSCommonJSModule::createStructure( JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* prototype = JSCommonJSModulePrototype::create(vm, globalObject, JSCommonJSModulePrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); @@ -700,7 +700,7 @@ JSCommonJSModule* JSCommonJSModule::create( bool hasEvaluated, JSValue parent) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto key = requireMapKey->value(globalObject); auto index = key->reverseFind(PLATFORM_SEP, key->length()); @@ -742,7 +742,7 @@ JSCommonJSModule* JSCommonJSModule::create( bool hasEvaluated, JSValue parent) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* requireMapKey = JSC::jsStringWithCache(vm, key); return JSCommonJSModule::create(globalObject, requireMapKey, exportsObject, hasEvaluated, parent); } @@ -776,7 +776,7 @@ bool JSCommonJSModule::evaluate( { Vector propertyNames; JSC::MarkedArgumentBuffer arguments; - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); generator(globalObject, JSC::Identifier::fromString(vm, key), propertyNames, arguments); RETURN_IF_EXCEPTION(throwScope, false); @@ -795,7 +795,7 @@ void populateESMExports( JSC::MarkedArgumentBuffer& exportValues, bool ignoreESModuleAnnotation) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); const Identifier& esModuleMarker = vm.propertyNames->__esModule; // Bun's intepretation of the "__esModule" annotation: @@ -1077,7 +1077,7 @@ const JSC::ClassInfo RequireFunctionPrototype::s_info = { "require"_s, &Base::s_ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) { auto* globalObject = jsCast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSCommonJSModule* thisObject = jsDynamicCast(callframe->thisValue()); @@ -1144,7 +1144,7 @@ bool JSCommonJSModule::evaluate( ResolvedSource& source, bool isBuiltIn) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto sourceProvider = Zig::SourceProvider::create(jsCast(globalObject), source, JSC::SourceProviderSourceType::Program, isBuiltIn); this->ignoreESModuleAnnotation = source.tag == ResolvedSourceTagPackageJSONTypeModule; if (this->hasEvaluated) @@ -1188,7 +1188,7 @@ std::optional createCommonJSModule( } if (!moduleObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* requireMapKey = specifierValue.toString(globalObject); auto index = sourceURL.reverseFind(PLATFORM_SEP, sourceURL.length()); JSString* dirname; @@ -1224,7 +1224,7 @@ std::optional createCommonJSModule( Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) -> void { auto* globalObject = jsCast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue keyValue = identifierToJSValue(vm, moduleKey); JSValue entry = globalObject->requireMap()->get(globalObject, keyValue); diff --git a/src/bun.js/bindings/ConsoleObject.cpp b/src/bun.js/bindings/ConsoleObject.cpp index 2d4653beefbfff..3eab5e2ad34726 100644 --- a/src/bun.js/bindings/ConsoleObject.cpp +++ b/src/bun.js/bindings/ConsoleObject.cpp @@ -39,7 +39,7 @@ void ConsoleObject::messageWithTypeAndLevel(MessageType type, MessageLevel level client->messageWithTypeAndLevel(type, level, globalObject, arguments.copyRef()); } } - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto args = arguments.ptr(); JSC__JSValue jsArgs[255]; diff --git a/src/bun.js/bindings/DOMURL.cpp b/src/bun.js/bindings/DOMURL.cpp index 7c59c949501e0c..690dbff4aa142c 100644 --- a/src/bun.js/bindings/DOMURL.cpp +++ b/src/bun.js/bindings/DOMURL.cpp @@ -57,6 +57,7 @@ static inline String redact(const String& input) inline DOMURL::DOMURL(URL&& completeURL) : m_url(WTFMove(completeURL)) + , m_initialURLCostForGC(std::min(static_cast(m_url.string().impl()->costDuringGC()), std::numeric_limits::max())) { ASSERT(m_url.isValid()); } diff --git a/src/bun.js/bindings/DOMURL.h b/src/bun.js/bindings/DOMURL.h index 56db692140943e..cb4bba6d8b2f35 100644 --- a/src/bun.js/bindings/DOMURL.h +++ b/src/bun.js/bindings/DOMURL.h @@ -65,6 +65,10 @@ class DOMURL final : public RefCounted, public CanMakeWeakPtr, p { return sizeof(DOMURL) + m_url.string().sizeInBytes(); } + size_t memoryCostForGC() const + { + return sizeof(DOMURL) + m_initialURLCostForGC; + } private: static ExceptionOr> create(const String& url, const URL& base); @@ -75,6 +79,7 @@ class DOMURL final : public RefCounted, public CanMakeWeakPtr, p URL m_url; RefPtr m_searchParams; + short m_initialURLCostForGC { 0 }; }; } // namespace WebCore diff --git a/src/bun.js/bindings/ErrorCode.cpp b/src/bun.js/bindings/ErrorCode.cpp index 702290f8251175..0d8df8f13e0b5a 100644 --- a/src/bun.js/bindings/ErrorCode.cpp +++ b/src/bun.js/bindings/ErrorCode.cpp @@ -29,7 +29,7 @@ JSC_DEFINE_HOST_FUNCTION(NodeError_proto_toString, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto thisVal = callFrame->thisValue(); @@ -192,13 +192,13 @@ JSC::JSObject* createError(VM& vm, Zig::GlobalObject* globalObject, ErrorCode co JSObject* createError(JSC::JSGlobalObject* globalObject, ErrorCode code, const String& message, bool isDOMExceptionPrototype) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); return createError(vm, globalObject, code, jsString(vm, message), isDOMExceptionPrototype); } JSObject* createError(Zig::JSGlobalObject* globalObject, ErrorCode code, JSC::JSValue message, bool isDOMExceptionPrototype) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); return createError(vm, globalObject, code, message, isDOMExceptionPrototype); } @@ -226,7 +226,7 @@ WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg) } case JSC::JSType::InternalFunctionType: case JSC::JSType::JSFunctionType: { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto catchScope = DECLARE_CATCH_SCOPE(vm); auto name = JSC::getCalculatedDisplayName(vm, cell->getObject()); if (catchScope.exception()) { @@ -254,7 +254,7 @@ WTF::String JSValueToStringSafe(JSC::JSGlobalObject* globalObject, JSValue arg) WTF::String determineSpecificType(JSC::JSGlobalObject* globalObject, JSValue value) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); ASSERT(!value.isEmpty()); @@ -367,7 +367,7 @@ WTF::String ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* gl result.append("The "_s); - if (arg_name.contains(' ')) { + if (arg_name.endsWith(" argument"_s)) { result.append(arg_name); } else { result.append("\""_s); @@ -379,13 +379,17 @@ WTF::String ERR_INVALID_ARG_TYPE(JSC::ThrowScope& scope, JSC::JSGlobalObject* gl unsigned length = expected_types.size(); if (length == 1) { result.append(expected_types.at(0).toWTFString(globalObject)); + } else if (length == 2) { + result.append(expected_types.at(0).toWTFString(globalObject)); + result.append(" or "_s); + result.append(expected_types.at(1).toWTFString(globalObject)); } else { for (unsigned i = 0; i < length - 1; i++) { JSValue expected_type = expected_types.at(i); - if (i > 0) result.append(", "_s); result.append(expected_type.toWTFString(globalObject)); + result.append(", "_s); } - result.append(" or "_s); + result.append("or "_s); result.append(expected_types.at(length - 1).toWTFString(globalObject)); } @@ -547,7 +551,7 @@ JSC::EncodedJSValue INVALID_ARG_VALUE_RangeError(JSC::ThrowScope& throwScope, JS auto value_string = JSValueToStringSafe(globalObject, value); RETURN_IF_EXCEPTION(throwScope, {}); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto message = makeString("The "_s, type, " '"_s, name, "' "_s, reason, ". Received "_s, value_string); auto* structure = createErrorStructure(vm, globalObject, ErrorType::RangeError, "RangeError"_s, "ERR_INVALID_ARG_VALUE"_s, false); auto error = JSC::ErrorInstance::create(vm, structure, message, jsUndefined(), nullptr, JSC::RuntimeType::TypeNothing, ErrorType::RangeError, true); @@ -745,7 +749,7 @@ void throwCryptoOperationFailed(JSGlobalObject* globalObject, JSC::ThrowScope& s JSC_DEFINE_HOST_FUNCTION(jsFunctionMakeAbortError, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { auto* globalObject = reinterpret_cast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto message = callFrame->argument(0); if (message.isUndefined()) message = JSC::jsString(vm, String("The operation was aborted"_s)); @@ -806,7 +810,7 @@ JSC::EncodedJSValue Bun::throwError(JSC::JSGlobalObject* globalObject, JSC::Thro JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); EXPECT_ARG_COUNT(1); @@ -1021,6 +1025,17 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject return JSC::JSValue::encode(createError(globalObject, error, message)); } + case ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS: { + auto arg0 = callFrame->argument(1); + if (!arg0.isUndefined()) { + auto str0 = arg0.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + auto message = makeString("\""_s, str0, "\" is outside of buffer bounds"_s); + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, message)); + } + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, "Attempt to access memory outside buffer bounds"_s)); + } + case ErrorCode::ERR_IPC_DISCONNECTED: return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_IPC_DISCONNECTED, "IPC channel is already disconnected"_s)); case ErrorCode::ERR_SERVER_NOT_RUNNING: @@ -1031,8 +1046,6 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_SOCKET_BAD_TYPE, "Bad socket type specified. Valid types are: udp4, udp6"_s)); case ErrorCode::ERR_ZLIB_INITIALIZATION_FAILED: return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_ZLIB_INITIALIZATION_FAILED, "Initialization failed"_s)); - case ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS: - return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_BUFFER_OUT_OF_BOUNDS, "Attempt to access memory outside buffer bounds"_s)); case ErrorCode::ERR_IPC_ONE_PIPE: return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_IPC_ONE_PIPE, "Child process can have only one IPC pipe"_s)); case ErrorCode::ERR_SOCKET_ALREADY_BOUND: @@ -1065,6 +1078,8 @@ JSC_DEFINE_HOST_FUNCTION(Bun::jsFunctionMakeErrorWithCode, (JSC::JSGlobalObject return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_STREAM_UNABLE_TO_PIPE, "Cannot pipe to a closed or destroyed stream"_s)); case ErrorCode::ERR_ILLEGAL_CONSTRUCTOR: return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_ILLEGAL_CONSTRUCTOR, "Illegal constructor"_s)); + case ErrorCode::ERR_DIR_CLOSED: + return JSC::JSValue::encode(createError(globalObject, ErrorCode::ERR_DIR_CLOSED, "Directory handle was closed"_s)); default: { break; diff --git a/src/bun.js/bindings/ErrorCode.ts b/src/bun.js/bindings/ErrorCode.ts index d191b106651c4a..5fc20865787a16 100644 --- a/src/bun.js/bindings/ErrorCode.ts +++ b/src/bun.js/bindings/ErrorCode.ts @@ -92,6 +92,9 @@ const errors: ErrorCodeMapping = [ // Console ["ERR_CONSOLE_WRITABLE_STREAM", TypeError, "TypeError"], + // FS + ["ERR_DIR_CLOSED", Error], + // DNS ["ERR_DNS_SET_SERVERS_FAILED", Error], diff --git a/src/bun.js/bindings/ErrorStackTrace.cpp b/src/bun.js/bindings/ErrorStackTrace.cpp index 2973aee6809db5..ef09b69384d40a 100644 --- a/src/bun.js/bindings/ErrorStackTrace.cpp +++ b/src/bun.js/bindings/ErrorStackTrace.cpp @@ -257,7 +257,7 @@ void JSCStackTrace::getFramesForCaller(JSC::VM& vm, JSC::CallFrame* callFrame, J JSCStackTrace JSCStackTrace::captureCurrentJSStackTrace(Zig::GlobalObject* globalObject, JSC::CallFrame* callFrame, size_t frameLimit, JSC::JSValue caller) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (!callFrame) { return JSCStackTrace(); } diff --git a/src/bun.js/bindings/EventLoopTaskNoContext.cpp b/src/bun.js/bindings/EventLoopTaskNoContext.cpp new file mode 100644 index 00000000000000..473bc3f11f2c69 --- /dev/null +++ b/src/bun.js/bindings/EventLoopTaskNoContext.cpp @@ -0,0 +1,17 @@ +#include "EventLoopTaskNoContext.h" + +namespace Bun { + +WTF_MAKE_ISO_ALLOCATED_IMPL(EventLoopTaskNoContext); + +extern "C" void Bun__EventLoopTaskNoContext__performTask(EventLoopTaskNoContext* task) +{ + task->performTask(); +} + +extern "C" void* Bun__EventLoopTaskNoContext__createdInBunVm(const EventLoopTaskNoContext* task) +{ + return task->createdInBunVm(); +} + +} // namespace Bun diff --git a/src/bun.js/bindings/EventLoopTaskNoContext.h b/src/bun.js/bindings/EventLoopTaskNoContext.h new file mode 100644 index 00000000000000..0f3491ce7676e6 --- /dev/null +++ b/src/bun.js/bindings/EventLoopTaskNoContext.h @@ -0,0 +1,35 @@ +#pragma once + +#include "ZigGlobalObject.h" +#include "root.h" + +namespace Bun { + +// Just like WebCore::EventLoopTask but does not take a ScriptExecutionContext +class EventLoopTaskNoContext { + WTF_MAKE_ISO_ALLOCATED(EventLoopTaskNoContext); + +public: + EventLoopTaskNoContext(JSC::JSGlobalObject* globalObject, Function&& task) + : m_createdInBunVm(defaultGlobalObject(globalObject)->bunVM()) + , m_task(WTFMove(task)) + { + } + + void performTask() + { + m_task(); + delete this; + } + + void* createdInBunVm() const { return m_createdInBunVm; } + +private: + void* m_createdInBunVm; + Function m_task; +}; + +extern "C" void Bun__EventLoopTaskNoContext__performTask(EventLoopTaskNoContext* task); +extern "C" void* Bun__EventLoopTaskNoContext__createdInBunVm(const EventLoopTaskNoContext* task); + +} // namespace Bun diff --git a/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp b/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp index 0497c1c6a6d360..6e5168957932c6 100644 --- a/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp +++ b/src/bun.js/bindings/ExposeNodeModuleGlobals.cpp @@ -86,7 +86,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsCustomGetterGetNativeModule, (JSC::JSGlobalObject * l extern "C" void Bun__ExposeNodeModuleGlobals(Zig::GlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); #define PUT_CUSTOM_GETTER_SETTER(id, field) \ globalObject->putDirectCustomAccessor( \ vm, \ diff --git a/src/bun.js/bindings/HTMLEntryPoint.cpp b/src/bun.js/bindings/HTMLEntryPoint.cpp new file mode 100644 index 00000000000000..c805fea3f0373a --- /dev/null +++ b/src/bun.js/bindings/HTMLEntryPoint.cpp @@ -0,0 +1,41 @@ +#include "root.h" + +#include "JavaScriptCore/CallData.h" +#include +#include "InternalModuleRegistry.h" +#include "ModuleLoader.h" +#include "ZigGlobalObject.h" +#include + +namespace Bun { +using namespace JSC; +extern "C" JSInternalPromise* Bun__loadHTMLEntryPoint(Zig::GlobalObject* globalObject) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); + + JSValue htmlModule = globalObject->internalModuleRegistry()->requireId(globalObject, vm, InternalModuleRegistry::InternalHtml); + if (UNLIKELY(scope.exception())) { + return promise->rejectWithCaughtException(globalObject, scope); + } + + JSObject* htmlModuleObject = htmlModule.getObject(); + if (UNLIKELY(!htmlModuleObject)) { + BUN_PANIC("Failed to load HTML entry point"); + } + + MarkedArgumentBuffer args; + JSValue result = JSC::call(globalObject, htmlModuleObject, args, "Failed to load HTML entry point"_s); + if (UNLIKELY(scope.exception())) { + return promise->rejectWithCaughtException(globalObject, scope); + } + + promise = jsDynamicCast(result); + if (UNLIKELY(!promise)) { + BUN_PANIC("Failed to load HTML entry point"); + } + return promise; +} + +} diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index 0d922f5577cdd6..5eabac8118064c 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -55,7 +55,7 @@ using namespace WebCore; static JSC::EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame, const WTF::String& fromStr) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); switch (callFrame->argumentCount()) { @@ -183,7 +183,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireResolve, (JSC::JSGlobalObject * global extern "C" JSC::EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { auto* globalObject = jsCast(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); JSValue thisValue = callFrame->thisValue(); @@ -275,7 +275,7 @@ extern "C" bool Bun__isBunMain(JSC::JSGlobalObject* global, const BunString*); extern "C" JSC::EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* globalObject = jsDynamicCast(lexicalGlobalObject); @@ -346,7 +346,7 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { auto* globalObject = jsCast(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); auto thisValue = callFrame->thisValue(); diff --git a/src/bun.js/bindings/InspectorTestReporterAgent.cpp b/src/bun.js/bindings/InspectorTestReporterAgent.cpp index f93097cc46318b..84369818eb9dfd 100644 --- a/src/bun.js/bindings/InspectorTestReporterAgent.cpp +++ b/src/bun.js/bindings/InspectorTestReporterAgent.cpp @@ -126,7 +126,7 @@ void InspectorTestReporterAgent::reportTestFound(JSC::CallFrame* callFrame, int ZigStackFrame remappedFrame = {}; auto* globalObject = &m_globalObject; - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::StackVisitor::visit(callFrame, vm, [&](JSC::StackVisitor& visitor) -> WTF::IterationStatus { if (Zig::isImplementationVisibilityPrivate(visitor)) diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp index eb158d45286c0a..ca110c7138f4cd 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.cpp +++ b/src/bun.js/bindings/InternalModuleRegistry.cpp @@ -156,7 +156,7 @@ JSValue InternalModuleRegistry::requireId(JSGlobalObject* globalObject, VM& vm, // so we want to write it to the internal field when loaded. JSC_DEFINE_HOST_FUNCTION(InternalModuleRegistry::jsCreateInternalModuleById, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto id = callframe->argument(0).toUInt32(lexicalGlobalObject); diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index b8346a3ec386ff..662bad2b86a2ea 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -78,6 +78,8 @@ // #include #include +extern "C" bool Bun__Node__ZeroFillBuffers; + using namespace JSC; using namespace WebCore; @@ -212,7 +214,7 @@ std::optional byteLength(JSC::JSString* str, JSC::JSGlobalObject* lexica static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_t byteLength) { #if ASSERT_ENABLED - JSC::VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); #endif @@ -229,11 +231,12 @@ static JSUint8Array* allocBuffer(JSC::JSGlobalObject* lexicalGlobalObject, size_ return uint8Array; } + static JSUint8Array* allocBufferUnsafe(JSC::JSGlobalObject* lexicalGlobalObject, size_t byteLength) { #if ASSERT_ENABLED - JSC::VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); #endif @@ -448,7 +451,7 @@ extern "C" JSC::EncodedJSValue JSBuffer__bufferFromLength(JSC::JSGlobalObject* l // https://github.com/nodejs/node/blob/v22.9.0/lib/buffer.js#L404 static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSValue lengthValue = callFrame->argument(0); Bun::V::validateNumber(throwScope, lexicalGlobalObject, lengthValue, "size"_s, jsNumber(0), jsNumber(Bun::Buffer::kMaxLength)); @@ -456,6 +459,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocUnsafeBody(JS size_t length = lengthValue.toLength(lexicalGlobalObject); auto result = allocBufferUnsafe(lexicalGlobalObject, length); RETURN_IF_EXCEPTION(throwScope, {}); + if (Bun__Node__ZeroFillBuffers) memset(result->typedVector(), 0, length); RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); } @@ -541,12 +545,11 @@ static JSC::EncodedJSValue constructFromEncoding(JSGlobalObject* lexicalGlobalOb static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSValue arg0, JSValue arg1) { auto& vm = JSC::getVM(lexicalGlobalObject); - WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; - auto scope = DECLARE_THROW_SCOPE(vm); - auto* str = arg0.toString(lexicalGlobalObject); + WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; + auto* str = arg0.toString(lexicalGlobalObject); RETURN_IF_EXCEPTION(scope, {}); if (arg1 && arg1.isString()) { @@ -572,7 +575,7 @@ static inline JSC::EncodedJSValue constructBufferFromStringAndEncoding(JSC::JSGl // https://github.com/nodejs/node/blob/v22.9.0/lib/buffer.js#L391 static inline JSC::EncodedJSValue jsBufferConstructorFunction_allocBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue lengthValue = callFrame->argument(0); @@ -677,7 +680,9 @@ JSC_DEFINE_HOST_FUNCTION(constructSlowBuffer, (JSGlobalObject * lexicalGlobalObj static inline JSC::EncodedJSValue jsBufferByteLengthFromStringAndEncoding(JSC::JSGlobalObject* lexicalGlobalObject, JSString* str, WebCore::BufferEncodingType encoding) { - auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm()); + auto& vm = JSC::getVM(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + if (!str) { throwTypeError(lexicalGlobalObject, scope, "byteLength() expects a string"_s); return {}; @@ -692,16 +697,15 @@ static inline JSC::EncodedJSValue jsBufferByteLengthFromStringAndEncoding(JSC::J return {}; } + static inline JSC::EncodedJSValue jsBufferConstructorFunction_byteLengthBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { auto& vm = JSC::getVM(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; - auto scope = DECLARE_THROW_SCOPE(vm); - EnsureStillAliveScope arg0 = callFrame->argument(0); - EnsureStillAliveScope arg1 = callFrame->argument(1); if (callFrame->argumentCount() > 1) { @@ -781,19 +785,17 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_compareBody(JSC::J static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { auto& vm = JSC::getVM(lexicalGlobalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); + if (callFrame->argumentCount() < 1) { return constructBufferEmpty(lexicalGlobalObject); } + auto listValue = callFrame->argument(0); - auto arrayValue = callFrame->uncheckedArgument(0); - auto array = JSC::jsDynamicCast(arrayValue); - if (!array) { - throwTypeError(lexicalGlobalObject, throwScope, "Argument must be an array"_s); - return {}; - } + Bun::V::validateArray(throwScope, lexicalGlobalObject, listValue, "list"_s, jsUndefined()); + RETURN_IF_EXCEPTION(throwScope, {}); + auto array = JSC::jsDynamicCast(listValue); size_t arrayLength = array->length(); if (arrayLength < 1) { RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject)); @@ -816,22 +818,20 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS JSValue element = array->getIndex(lexicalGlobalObject, i); RETURN_IF_EXCEPTION(throwScope, {}); - if (auto* bufferView = JSC::jsDynamicCast(element)) { - if (UNLIKELY(bufferView->isDetached())) { - throwVMTypeError(lexicalGlobalObject, throwScope, "ArrayBufferView is detached"_s); - return {}; - } + auto* typedArray = JSC::jsDynamicCast(element); + if (!typedArray) { + return Bun::ERR::INVALID_ARG_TYPE(throwScope, lexicalGlobalObject, makeString("list["_s, i, "]"_s), "Buffer or Uint8Array"_s, element); + } + if (UNLIKELY(typedArray->isDetached())) { + return throwVMTypeError(lexicalGlobalObject, throwScope, "ArrayBufferView is detached"_s); + } - auto length = bufferView->byteLength(); + auto length = typedArray->byteLength(); - if (length > 0) - args.append(element); + if (length > 0) + args.append(element); - byteLength += length; - } else { - throwTypeError(lexicalGlobalObject, throwScope, "Buffer.concat expects Buffer or Uint8Array"_s); - return {}; - } + byteLength += length; } size_t availableLength = byteLength; @@ -866,7 +866,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_concatBody(JSC::JS size_t remain = byteLength; auto* head = outBuffer->typedVector(); - const int arrayLengthI = arrayLength; + const int arrayLengthI = args.size(); for (int i = 0; i < arrayLengthI && remain > 0; i++) { auto* bufferView = JSC::jsCast(args.at(i)); size_t length = std::min(remain, bufferView->byteLength()); @@ -945,7 +945,7 @@ static inline JSC::EncodedJSValue jsBufferConstructorFunction_copyBytesFromBody( static inline JSC::EncodedJSValue jsBufferConstructorFunction_isEncodingBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto encodingValue = callFrame->argument(0); if (!encodingValue.isString()) { @@ -1171,6 +1171,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_equalsBody(JSC::JSGl { auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); + if (callFrame->argumentCount() < 1) { throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); return {}; @@ -1201,6 +1202,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_equalsBody(JSC::JSGl RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsBoolean(normalizeCompareVal(result, a_length, b_length) == 0))); } + static inline JSC::EncodedJSValue jsBufferPrototypeFunction_fillBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -1354,6 +1356,7 @@ static int64_t indexOf(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* { auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); + if (callFrame->argumentCount() < 1) { throwVMError(lexicalGlobalObject, scope, createNotEnoughArgumentsError(lexicalGlobalObject)); return -1; @@ -1460,16 +1463,19 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_includesBody(JSC::JS auto index = indexOf(lexicalGlobalObject, callFrame, castedThis, false); return JSC::JSValue::encode(jsBoolean(index != -1)); } + static inline JSC::EncodedJSValue jsBufferPrototypeFunction_indexOfBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto index = indexOf(lexicalGlobalObject, callFrame, castedThis, false); return JSC::JSValue::encode(jsNumber(index)); } + static inline JSC::EncodedJSValue jsBufferPrototypeFunction_lastIndexOfBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto index = indexOf(lexicalGlobalObject, callFrame, castedThis, true); return JSC::JSValue::encode(jsNumber(index)); } + static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap16Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -1499,6 +1505,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap16Body(JSC::JSGl return JSC::JSValue::encode(castedThis); } + static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap32Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -1533,6 +1540,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap32Body(JSC::JSGl return JSC::JSValue::encode(castedThis); } + static inline JSC::EncodedJSValue jsBufferPrototypeFunction_swap64Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); @@ -1622,11 +1630,12 @@ static inline JSC::EncodedJSValue jsBufferToString(JSC::VM& vm, JSC::JSGlobalObj case WebCore::BufferEncodingType::base64url: case WebCore::BufferEncodingType::hex: { ret = Bun__encoding__toString(reinterpret_cast(castedThis->vector()) + offset, length, lexicalGlobalObject, static_cast(encoding)); + RETURN_IF_EXCEPTION(scope, {}); break; } default: { throwTypeError(lexicalGlobalObject, scope, "Unsupported encoding? This shouldn't happen"_s); - break; + return {}; } } @@ -1664,6 +1673,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_toStringBody(JSC::JS { auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); + uint32_t start = 0; uint32_t end = castedThis->byteLength(); uint32_t byteLength = end; @@ -1718,6 +1728,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_SliceWithEncoding(JS { auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = JSC::jsDynamicCast(callFrame->thisValue()); const JSValue startValue = callFrame->argument(0); const JSValue endValue = callFrame->argument(1); @@ -1759,7 +1770,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_SliceWithEncoding(JS // JSC_DEFINE_JIT_OPERATION(jsBufferPrototypeToStringWithoutTypeChecks, JSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSUint8Array* thisValue, JSString* encodingValue)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -1810,6 +1821,7 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunctionWriteWithEncoding(JSC { auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = JSC::jsDynamicCast(callFrame->thisValue()); JSString* text = callFrame->argument(0).toStringOrNull(lexicalGlobalObject); @@ -1834,13 +1846,13 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunctionWriteWithEncoding(JSC static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation::ClassParameter castedThis) { auto& vm = JSC::getVM(lexicalGlobalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + uint32_t offset = 0; uint32_t length = castedThis->byteLength(); uint32_t max = length; WebCore::BufferEncodingType encoding = WebCore::BufferEncodingType::utf8; - auto scope = DECLARE_THROW_SCOPE(vm); - if (UNLIKELY(callFrame->argumentCount() == 0)) { throwTypeError(lexicalGlobalObject, scope, "Not enough arguments"_s); return {}; @@ -1925,7 +1937,6 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_writeBody(JSC::JSGlo extern "C" JSC::EncodedJSValue JSBuffer__fromMmap(Zig::GlobalObject* globalObject, void* ptr, size_t length) { - auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); @@ -1953,14 +1964,17 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_alloc, (JSGlobalObject * le { return jsBufferConstructorFunction_allocBody(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_allocUnsafe, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferConstructorFunction_allocUnsafeBody(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_allocUnsafeSlow, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferConstructorFunction_allocUnsafeSlowBody(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_byteLength, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferConstructorFunction_byteLengthBody(lexicalGlobalObject, callFrame); @@ -2030,7 +2044,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(jsBufferConstructorAll JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int byteLength)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); IGNORE_WARNINGS_BEGIN("frame-address") CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END @@ -2040,7 +2054,7 @@ JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocWithoutTypeChecks, JSUint8Array JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int byteLength)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); IGNORE_WARNINGS_BEGIN("frame-address") CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END @@ -2050,7 +2064,7 @@ JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeWithoutTypeChecks, JSUint JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeSlowWithoutTypeChecks, JSUint8Array*, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int byteLength)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); IGNORE_WARNINGS_BEGIN("frame-address") CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END @@ -2079,46 +2093,57 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_compare, (JSGlobalObject * le { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "compare"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_copy, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "copy"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_equals, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "equals"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_fill, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "fill"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_includes, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "includes"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_indexOf, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "indexOf"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_lastIndexOf, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "lastIndexOf"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_swap16, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "swap16"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_swap32, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "swap32"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_swap64, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "swap64"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_toString, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "toString"); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_write, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return IDLOperation::call(*lexicalGlobalObject, *callFrame, "write"); @@ -2163,26 +2188,32 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_utf8Slice, (JSGlobalObject * { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_utf16leSlice, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_latin1Slice, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_asciiSlice, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_base64Slice, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_base64urlSlice, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); } + JSC_DEFINE_HOST_FUNCTION(jsBufferPrototypeFunction_hexSlice, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { return jsBufferPrototypeFunction_SliceWithEncoding(lexicalGlobalObject, callFrame); @@ -2301,6 +2332,8 @@ void JSBufferPrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis) JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); reifyStaticProperties(vm, JSBuffer::info(), JSBufferPrototypeTableValues, *this); + ALIAS("toLocaleString", "toString"); + ALIAS("readUintBE", "readUIntBE"); ALIAS("readUintLE", "readUIntLE"); ALIAS("readUint8", "readUInt8"); @@ -2367,6 +2400,7 @@ JSC::JSObject* createBufferPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObj { return JSBufferPrototype::create(vm, globalObject, JSBufferPrototype::createStructure(vm, globalObject, globalObject->m_typedArrayUint8.prototype(globalObject))); } + JSC::JSObject* createBufferConstructor(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSObject* bufferPrototype) { return JSBufferConstructor::create( @@ -2380,8 +2414,9 @@ JSC::JSObject* createBufferConstructor(JSC::VM& vm, JSC::JSGlobalObject* globalO static inline JSC::EncodedJSValue createJSBufferFromJS(JSC::JSGlobalObject* lexicalGlobalObject, JSValue newTarget, ArgList args) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); + size_t argsCount = args.size(); if (argsCount == 0) { RELEASE_AND_RETURN(throwScope, constructBufferEmpty(lexicalGlobalObject)); @@ -2563,7 +2598,7 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal bool JSBuffer__isBuffer(JSC::JSGlobalObject* lexicalGlobalObject, JSC::EncodedJSValue value) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSC::JSValue jsValue = JSC::JSValue::decode(value); if (!jsValue || !jsValue.isCell()) diff --git a/src/bun.js/bindings/JSBufferList.cpp b/src/bun.js/bindings/JSBufferList.cpp index 32c65f387d1dd0..4f10dd85bc5979 100644 --- a/src/bun.js/bindings/JSBufferList.cpp +++ b/src/bun.js/bindings/JSBufferList.cpp @@ -14,7 +14,7 @@ using namespace JSC; static JSC_DECLARE_CUSTOM_GETTER(JSBufferList_getLength); static JSC_DEFINE_CUSTOM_GETTER(JSBufferList_getLength, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSBufferList* bufferList = JSC::jsDynamicCast(JSValue::decode(thisValue)); @@ -437,7 +437,7 @@ JSBufferListConstructor* JSBufferListConstructor::create(JSC::VM& vm, JSC::JSGlo JSC::EncodedJSValue JSBufferListConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSBufferList* bufferList = JSBufferList::create( vm, lexicalGlobalObject, reinterpret_cast(lexicalGlobalObject)->JSBufferListStructure()); return JSC::JSValue::encode(bufferList); diff --git a/src/bun.js/bindings/JSBundlerPlugin.cpp b/src/bun.js/bindings/JSBundlerPlugin.cpp index e4f9253fe0fe58..d0130a9803ab23 100644 --- a/src/bun.js/bindings/JSBundlerPlugin.cpp +++ b/src/bun.js/bindings/JSBundlerPlugin.cpp @@ -203,7 +203,7 @@ JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_addFilter, (JSC::JSGlobalObject } uint32_t isOnLoad = callFrame->argument(2).toUInt32(globalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); unsigned index = 0; if (isOnLoad) { @@ -325,7 +325,7 @@ int BundlerPlugin::NativePluginList::call(JSC::VM& vm, BundlerPlugin* plugin, in } JSC_DEFINE_HOST_FUNCTION(jsBundlerPluginFunction_onBeforeParse, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSBundlerPlugin* thisObject = jsCast(callFrame->thisValue()); if (thisObject->plugin.tombstoned) { @@ -544,7 +544,7 @@ extern "C" void JSBundlerPlugin__matchOnResolve(Bun::JSBundlerPlugin* plugin, co } WTF::String pathStr = path ? path->toWTFString(BunString::ZeroCopy) : WTF::String(); WTF::String importerStr = importer ? importer->toWTFString(BunString::ZeroCopy) : WTF::String(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSFunction* function = plugin->onResolveFunction.get(plugin); if (UNLIKELY(!function)) diff --git a/src/bun.js/bindings/JSCTestingHelpers.cpp b/src/bun.js/bindings/JSCTestingHelpers.cpp index 78092eec0c3a32..6807ad2b2ee8fc 100644 --- a/src/bun.js/bindings/JSCTestingHelpers.cpp +++ b/src/bun.js/bindings/JSCTestingHelpers.cpp @@ -13,7 +13,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsUTF16String, (JSGlobalObject * globalObject, CallFrame* callframe)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue value = callframe->argument(0); if (value.isString()) { @@ -33,7 +33,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsLatin1String, (JSGlobalObject * globalObject, CallFrame* callframe)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue value = callframe->argument(0); if (value.isString()) { @@ -51,7 +51,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsLatin1String, JSC::JSValue createJSCTestingHelpers(Zig::GlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSObject* object = JSC::constructEmptyObject(globalObject); diff --git a/src/bun.js/bindings/JSDOMExceptionHandling.cpp b/src/bun.js/bindings/JSDOMExceptionHandling.cpp index 075026ab6dba5f..b673cc1a439b87 100644 --- a/src/bun.js/bindings/JSDOMExceptionHandling.cpp +++ b/src/bun.js/bindings/JSDOMExceptionHandling.cpp @@ -42,7 +42,7 @@ using namespace JSC; void reportException(JSGlobalObject* lexicalGlobalObject, JSC::Exception* exception, CachedScript* cachedScript, bool fromModule, ExceptionDetails* exceptionDetails) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); if (vm.isTerminationException(exception)) return; @@ -86,7 +86,7 @@ void reportException(JSGlobalObject* lexicalGlobalObject, JSC::Exception* except void reportException(JSGlobalObject* lexicalGlobalObject, JSValue exceptionValue, CachedScript* cachedScript, bool fromModule) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); auto* exception = jsDynamicCast(exceptionValue); if (!exception) { @@ -136,7 +136,7 @@ String retrieveErrorMessage(JSGlobalObject& lexicalGlobalObject, VM& vm, JSValue void reportCurrentException(JSGlobalObject* lexicalGlobalObject) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_CATCH_SCOPE(vm); auto* exception = scope.exception(); scope.clearException(); @@ -145,7 +145,7 @@ void reportCurrentException(JSGlobalObject* lexicalGlobalObject) JSValue createDOMException(JSGlobalObject* lexicalGlobalObject, ExceptionCode ec, const String& message) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); if (UNLIKELY(vm.hasPendingTerminationException())) return jsUndefined(); diff --git a/src/bun.js/bindings/JSDOMFile.cpp b/src/bun.js/bindings/JSDOMFile.cpp index c67cf8f62f6bcb..dbb2acfbd7f96e 100644 --- a/src/bun.js/bindings/JSDOMFile.cpp +++ b/src/bun.js/bindings/JSDOMFile.cpp @@ -66,7 +66,7 @@ class JSDOMFile : public JSC::InternalFunction { static JSC_HOST_CALL_ATTRIBUTES JSC::EncodedJSValue construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { auto* globalObject = defaultGlobalObject(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSObject* newTarget = asObject(callFrame->newTarget()); auto* constructor = globalObject->JSDOMFileConstructor(); Structure* structure = globalObject->JSBlobStructure(); diff --git a/src/bun.js/bindings/JSDOMWrapperCache.h b/src/bun.js/bindings/JSDOMWrapperCache.h index 7fa9a8d3e7dbd5..13991a006595fc 100644 --- a/src/bun.js/bindings/JSDOMWrapperCache.h +++ b/src/bun.js/bindings/JSDOMWrapperCache.h @@ -212,7 +212,7 @@ template inline void setSubclassStructureIfNeeded(JSC::JSGlob using WrapperClass = typename JSDOMWrapperConverterTraits::WrapperClass; - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); // If the new target isn't actually callable diff --git a/src/bun.js/bindings/JSFFIFunction.cpp b/src/bun.js/bindings/JSFFIFunction.cpp index e3a1fc3239a128..a8e73534b1e850 100644 --- a/src/bun.js/bindings/JSFFIFunction.cpp +++ b/src/bun.js/bindings/JSFFIFunction.cpp @@ -73,7 +73,7 @@ extern "C" FFICallbackFunctionWrapper* Bun__createFFICallbackFunction( extern "C" Zig::JSFFIFunction* Bun__CreateFFIFunctionWithData(Zig::GlobalObject* globalObject, const ZigString* symbolName, unsigned argCount, Zig::FFIFunction functionPointer, bool strong, void* data) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); Zig::JSFFIFunction* function = Zig::JSFFIFunction::create(vm, globalObject, argCount, symbolName != nullptr ? Zig::toStringCopy(*symbolName) : String(), functionPointer, JSC::NoIntrinsic); if (strong) globalObject->trackFFIFunction(function); @@ -118,7 +118,7 @@ extern "C" JSC::EncodedJSValue Bun__CreateFFIFunctionValue(Zig::GlobalObject* gl { if (addPtrField) { auto* function = Zig::JSFFIFunction::createForFFI(globalObject->vm(), globalObject, argCount, symbolName != nullptr ? Zig::toStringCopy(*symbolName) : String(), reinterpret_cast(functionPointer)); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); // We should only expose the "ptr" field when it's a JSCallback for bun:ffi. // Not for internal usages of this function type. // We should also consider a separate JSFunction type for our usage to not have this branch in the first place... @@ -198,7 +198,7 @@ FFI_Callback_call(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::Enc { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; for (size_t i = 0; i < argCount; ++i) arguments.appendWithCrashOnOverflow(JSC::JSValue::decode(args[i])); @@ -224,7 +224,7 @@ FFI_Callback_threadsafe_call(FFICallbackFunctionWrapper& wrapper, size_t argCoun WebCore::ScriptExecutionContext::postTaskTo(globalObject->scriptExecutionContext()->identifier(), [argsVec = WTFMove(argsVec), wrapper](WebCore::ScriptExecutionContext& ctx) mutable { auto* globalObject = JSC::jsCast(ctx.jsGlobalObject()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; auto* function = wrapper.m_function.get(); for (size_t i = 0; i < argsVec.size(); ++i) @@ -244,7 +244,7 @@ FFI_Callback_call_0(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::E { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; @@ -264,7 +264,7 @@ FFI_Callback_call_1(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::E { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); @@ -285,7 +285,7 @@ FFI_Callback_call_2(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::E { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); @@ -306,7 +306,7 @@ extern "C" JSC::EncodedJSValue FFI_Callback_call_3(FFICallbackFunctionWrapper& w { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); @@ -328,7 +328,7 @@ extern "C" JSC::EncodedJSValue FFI_Callback_call_4(FFICallbackFunctionWrapper& w { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); @@ -351,7 +351,7 @@ extern "C" JSC::EncodedJSValue FFI_Callback_call_5(FFICallbackFunctionWrapper& w { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); @@ -376,7 +376,7 @@ FFI_Callback_call_6(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::E { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); @@ -402,7 +402,7 @@ FFI_Callback_call_7(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::E { auto* function = wrapper.m_function.get(); auto* globalObject = wrapper.globalObject.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer arguments; arguments.append(JSC::JSValue::decode(args[0])); diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 0facb458fd5c92..4940a0f7864c02 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -152,7 +152,7 @@ class JSMockImplementation final : public JSNonFinalObject { static JSMockImplementation* create(JSC::JSGlobalObject* globalObject, JSC::Structure* structure, Kind kind, JSC::JSValue heldValue, bool isOnce) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSMockImplementation* impl = new (NotNull, allocateCell(vm)) JSMockImplementation(vm, structure, kind); impl->finishCreation(vm, heldValue, isOnce ? jsNumber(1) : jsUndefined()); return impl; @@ -490,7 +490,7 @@ DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSMockFunction); static void pushImpl(JSMockFunction* fn, JSGlobalObject* jsGlobalObject, JSMockImplementation::Kind kind, JSValue value) { Zig::GlobalObject* globalObject = jsCast(jsGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (auto* current = tryJSDynamicCast(fn->fallbackImplmentation)) { current->underlyingValue.set(vm, current, value); @@ -510,7 +510,7 @@ static void pushImpl(JSMockFunction* fn, JSGlobalObject* jsGlobalObject, JSMockI static void pushImplOnce(JSMockFunction* fn, JSGlobalObject* jsGlobalObject, JSMockImplementation::Kind kind, JSValue value) { Zig::GlobalObject* globalObject = jsCast(jsGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSMockImplementation* impl = JSMockImplementation::create(globalObject, globalObject->mockModule.mockImplementationStructure.getInitializedOnMainThread(globalObject), kind, value, true); @@ -798,7 +798,7 @@ static JSValue createMockResult(JSC::VM& vm, Zig::GlobalObject* globalObject, co JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObject, CallFrame* callframe)) { Zig::GlobalObject* globalObject = jsCast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSMockFunction* fn = jsDynamicCast(callframe->jsCallee()); auto scope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(!fn)) { @@ -954,7 +954,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetMockImplementation, (JSC::JSGlobalObje JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1017,7 +1017,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetMockName, (JSC::JSGlobalObject * globa JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue) @@ -1033,7 +1033,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockClear, (JSC::JSGlobalObject * globalO JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1046,7 +1046,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReset, (JSC::JSGlobalObject * globalO JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1059,7 +1059,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRestore, (JSC::JSGlobalObject * globa JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1069,7 +1069,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRestore, (JSC::JSGlobalObject * globa } JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockImplementation, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* globalObject = jsCast(lexicalGlobalObject); JSValue thisValue = callframe->thisValue(); @@ -1091,7 +1091,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockImplementation, (JSC::JSGlobalObject } JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockImplementationOnce, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* globalObject = jsCast(lexicalGlobalObject); JSValue thisValue = callframe->thisValue(); @@ -1116,7 +1116,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockName, (JSC::JSGlobalObject * globalOb JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1136,7 +1136,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReturnThis, (JSC::JSGlobalObject * gl JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1149,7 +1149,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReturnValue, (JSC::JSGlobalObject * g JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1162,7 +1162,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockReturnValueOnce, (JSC::JSGlobalObject JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1175,7 +1175,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockResolvedValue, (JSC::JSGlobalObject * JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1188,7 +1188,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockResolvedValueOnce, (JSC::JSGlobalObje JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1201,7 +1201,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValue, (JSC::JSGlobalObject * JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1214,7 +1214,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce, (JSC::JSGlobalObje JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1224,7 +1224,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionMockRejectedValueOnce, (JSC::JSGlobalObje } JSC_DEFINE_HOST_FUNCTION(jsMockFunctionGetter_mockGetLastCall, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSValue thisObject = callframe->thisValue(); if (UNLIKELY(!thisObject.isObject())) { @@ -1318,7 +1318,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionWithImplementation, (JSC::JSGlobalObject JSValue thisValue = callframe->thisValue(); JSMockFunction* thisObject = jsDynamicCast(thisValue); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_IS_MOCK_FUNCTION(thisValue); @@ -1425,7 +1425,7 @@ BUN_DEFINE_HOST_FUNCTION(JSMock__jsClearAllMocks, (JSC::JSGlobalObject * globalO BUN_DEFINE_HOST_FUNCTION(JSMock__jsSpyOn, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* globalObject = jsDynamicCast(lexicalGlobalObject); @@ -1544,7 +1544,7 @@ BUN_DEFINE_HOST_FUNCTION(JSMock__jsSpyOn, (JSC::JSGlobalObject * lexicalGlobalOb BUN_DEFINE_HOST_FUNCTION(JSMock__jsMockFn, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* globalObject = jsCast(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); diff --git a/src/bun.js/bindings/JSNextTickQueue.cpp b/src/bun.js/bindings/JSNextTickQueue.cpp index 7b9c1f98bb10f3..642ff260453b26 100644 --- a/src/bun.js/bindings/JSNextTickQueue.cpp +++ b/src/bun.js/bindings/JSNextTickQueue.cpp @@ -64,7 +64,7 @@ DEFINE_VISIT_CHILDREN(JSNextTickQueue); JSNextTickQueue* JSNextTickQueue::create(JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* obj = create(vm, createStructure(vm, globalObject, jsNull())); return obj; } diff --git a/src/bun.js/bindings/JSPropertyIterator.cpp b/src/bun.js/bindings/JSPropertyIterator.cpp index afd53692c7b4b4..fa4f76628c41c8 100644 --- a/src/bun.js/bindings/JSPropertyIterator.cpp +++ b/src/bun.js/bindings/JSPropertyIterator.cpp @@ -38,7 +38,7 @@ class 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) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue value = JSValue::decode(encodedValue); JSC::JSObject* object = value.getObject(); diff --git a/src/bun.js/bindings/JSPropertyIterator.zig b/src/bun.js/bindings/JSPropertyIterator.zig index 56f763551fd87d..854128256d44a4 100644 --- a/src/bun.js/bindings/JSPropertyIterator.zig +++ b/src/bun.js/bindings/JSPropertyIterator.zig @@ -2,12 +2,12 @@ const bun = @import("root").bun; const JSC = bun.JSC; //extern "C" EncodedJSValue Bun__JSPropertyIterator__getNameAndValue(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, BunString* propertyName, size_t i) -extern "C" fn Bun__JSPropertyIterator__create(globalObject: *JSC.JSGlobalObject, encodedValue: JSC.JSValue, *usize, own_properties_only: bool, only_non_index_properties: bool) ?*anyopaque; -extern "C" fn Bun__JSPropertyIterator__getNameAndValue(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; -extern "C" fn Bun__JSPropertyIterator__getNameAndValueNonObservable(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; -extern "C" fn Bun__JSPropertyIterator__getName(iter: ?*anyopaque, propertyName: *bun.String, i: usize) void; -extern "C" fn Bun__JSPropertyIterator__deinit(iter: ?*anyopaque) void; -extern "C" fn Bun__JSPropertyIterator__getLongestPropertyName(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque) usize; +extern "c" fn Bun__JSPropertyIterator__create(globalObject: *JSC.JSGlobalObject, encodedValue: JSC.JSValue, *usize, own_properties_only: bool, only_non_index_properties: bool) ?*anyopaque; +extern "c" fn Bun__JSPropertyIterator__getNameAndValue(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; +extern "c" fn Bun__JSPropertyIterator__getNameAndValueNonObservable(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; +extern "c" fn Bun__JSPropertyIterator__getName(iter: ?*anyopaque, propertyName: *bun.String, i: usize) void; +extern "c" fn Bun__JSPropertyIterator__deinit(iter: ?*anyopaque) void; +extern "c" fn Bun__JSPropertyIterator__getLongestPropertyName(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque) usize; pub const JSPropertyIteratorOptions = struct { skip_empty_name: bool, include_value: bool, diff --git a/src/bun.js/bindings/JSS3File.cpp b/src/bun.js/bindings/JSS3File.cpp index 7e2d2309b5ee6a..cea86dc84fb1dd 100644 --- a/src/bun.js/bindings/JSS3File.cpp +++ b/src/bun.js/bindings/JSS3File.cpp @@ -35,7 +35,7 @@ JSC_DECLARE_HOST_FUNCTION(functionS3File_stat); static JSC_DECLARE_CUSTOM_GETTER(getterS3File_bucket); static JSC_DEFINE_CUSTOM_GETTER(getterS3File_bucket, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsDynamicCast(JSValue::decode(thisValue)); @@ -122,7 +122,7 @@ JSS3File* JSS3File::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC:: JSValue constructS3FileInternal(JSC::JSGlobalObject* lexicalGlobalObject, void* ptr) { ASSERT(ptr); - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* globalObject = defaultGlobalObject(lexicalGlobalObject); auto* structure = globalObject->m_JSS3FileStructure.getInitializedOnMainThread(lexicalGlobalObject); @@ -131,7 +131,7 @@ JSValue constructS3FileInternal(JSC::JSGlobalObject* lexicalGlobalObject, void* JSValue constructS3File(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); void* ptr = JSS3File__construct(globalObject, callframe); RETURN_IF_EXCEPTION(scope, {}); @@ -142,7 +142,7 @@ JSValue constructS3File(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callf JSC::Structure* JSS3File::createStructure(JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* superPrototype = defaultGlobalObject(globalObject)->JSBlobPrototype(); auto* protoStructure = JSS3FilePrototype::createStructure(vm, globalObject, superPrototype); @@ -166,7 +166,7 @@ Structure* createJSS3FileStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObjec JSC_DEFINE_HOST_FUNCTION(functionS3File_presign, (JSGlobalObject * globalObject, CallFrame* callframe)) { auto* thisObject = jsDynamicCast(callframe->thisValue()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!thisObject) { Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_INVALID_THIS, "Expected a S3File instance"_s); @@ -179,7 +179,7 @@ JSC_DEFINE_HOST_FUNCTION(functionS3File_presign, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(functionS3File_stat, (JSGlobalObject * globalObject, CallFrame* callframe)) { auto* thisObject = jsDynamicCast(callframe->thisValue()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!thisObject) { Bun::throwError(globalObject, scope, Bun::ErrorCode::ERR_INVALID_THIS, "Expected a S3File instance"_s); diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index 42c4aac1d7bf5a..441f5582ac5520 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -87,7 +87,7 @@ static inline JSStringDecoder* jsStringDecoderCast(JSGlobalObject* globalObject, if (auto cast = jsDynamicCast(stringDecoderValue); LIKELY(cast)) return cast; - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (JSC::JSObject* thisObject = stringDecoderValue.getObject()) { @@ -562,7 +562,7 @@ JSStringDecoderConstructor* JSStringDecoderConstructor::create(JSC::VM& vm, JSC: JSC::EncodedJSValue JSStringDecoderConstructor::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto encoding = BufferEncodingType::utf8; auto jsEncoding = callFrame->argument(0); diff --git a/src/bun.js/bindings/JSWrappingFunction.cpp b/src/bun.js/bindings/JSWrappingFunction.cpp index 6a878a3bede65a..92899f6e528796 100644 --- a/src/bun.js/bindings/JSWrappingFunction.cpp +++ b/src/bun.js/bindings/JSWrappingFunction.cpp @@ -66,7 +66,7 @@ extern "C" JSC::EncodedJSValue Bun__JSWrappingFunction__create( Bun::NativeFunctionPtr functionPointer, JSC::EncodedJSValue wrappedFnEncoded) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue wrappedFn = JSC::JSValue::decode(wrappedFnEncoded); auto function = JSWrappingFunction::create(vm, globalObject, symbolName, functionPointer, wrappedFn); return JSC::JSValue::encode(function); diff --git a/src/bun.js/bindings/JSX509CertificatePrototype.h b/src/bun.js/bindings/JSX509CertificatePrototype.h index 4328cdd140d417..84614be24bef10 100644 --- a/src/bun.js/bindings/JSX509CertificatePrototype.h +++ b/src/bun.js/bindings/JSX509CertificatePrototype.h @@ -10,9 +10,9 @@ class VM; namespace Bun { -class JSX509CertificatePrototype final : public JSC::JSObject { +class JSX509CertificatePrototype final : public JSC::JSNonFinalObject { public: - using Base = JSC::JSObject; + using Base = JSC::JSNonFinalObject; static constexpr unsigned StructureFlags = Base::StructureFlags; static JSX509CertificatePrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) diff --git a/src/bun.js/bindings/KeyObject.cpp b/src/bun.js/bindings/KeyObject.cpp index 8d8715f8bec2c5..6a9b816f3d62dd 100644 --- a/src/bun.js/bindings/KeyObject.cpp +++ b/src/bun.js/bindings/KeyObject.cpp @@ -21,7 +21,9 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. +#include "root.h" #include "ErrorCode.h" +#include "BunCommonStrings.h" #include "KeyObject.h" #include "JavaScriptCore/JSArrayBufferView.h" #include "JavaScriptCore/JSCJSValue.h" @@ -324,7 +326,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPrivateKey, (JSC::JSGlobalObject * glo ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count < 1) { @@ -611,9 +613,9 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPrivateKey, (JSC::JSGlobalObject * glo auto impl = result.releaseNonNull(); return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); } else if (pKeyID == EVP_PKEY_X25519) { - auto result = CryptoKeyOKP::importPkcs8(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, Vector(std::span { (uint8_t*)data, byteLength }), true, CryptoKeyUsageSign); + auto result = CryptoKeyOKP::importPkcs8(CryptoAlgorithmIdentifier::X25519, CryptoKeyOKP::NamedCurve::X25519, Vector(std::span { (uint8_t*)data, byteLength }), true, CryptoKeyUsageDeriveKey); if (UNLIKELY(result == nullptr)) { - throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 private key"_s)); + throwException(globalObject, scope, createTypeError(globalObject, "Invalid X25519 private key"_s)); return {}; } auto impl = result.releaseNonNull(); @@ -709,7 +711,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPrivateKey, (JSC::JSGlobalObject * glo static JSC::EncodedJSValue KeyObject__createRSAFromPrivate(JSC::JSGlobalObject* globalObject, EVP_PKEY* pkey, WebCore::CryptoAlgorithmIdentifier alg) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); const RSA* rsa_key = EVP_PKEY_get0_RSA(pkey); @@ -732,7 +734,7 @@ static JSC::EncodedJSValue KeyObject__createRSAFromPrivate(JSC::JSGlobalObject* static JSC::EncodedJSValue KeyObject__createECFromPrivate(JSC::JSGlobalObject* globalObject, EVP_PKEY* pkey, CryptoKeyEC::NamedCurve namedCurve, WebCore::CryptoAlgorithmIdentifier alg) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey); @@ -780,7 +782,7 @@ static JSC::EncodedJSValue KeyObject__createECFromPrivate(JSC::JSGlobalObject* g static JSC::EncodedJSValue KeyObject__createOKPFromPrivate(JSC::JSGlobalObject* globalObject, const WebCore::CryptoKeyOKP::KeyMaterial keyData, CryptoKeyOKP::NamedCurve namedCurve, WebCore::CryptoAlgorithmIdentifier alg) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); Vector public_key(ED25519_PUBLIC_KEY_LEN); @@ -805,7 +807,7 @@ static JSC::EncodedJSValue KeyObject__createOKPFromPrivate(JSC::JSGlobalObject* static JSC::EncodedJSValue KeyObject__createPublicFromPrivate(JSC::JSGlobalObject* globalObject, EVP_PKEY* pkey) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto pKeyID = EVP_PKEY_id(pkey); @@ -862,7 +864,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPublicKey, (JSC::JSGlobalObject * glob { ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); @@ -987,7 +989,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPublicKey, (JSC::JSGlobalObject * glob } return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); } else if (jwk.crv == "X25519"_s) { - auto result = CryptoKeyOKP::importPublicJwk(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, WTFMove(jwk), true, CryptoKeyUsageVerify); + auto result = CryptoKeyOKP::importPublicJwk(CryptoAlgorithmIdentifier::X25519, CryptoKeyOKP::NamedCurve::X25519, WTFMove(jwk), true, CryptoKeyUsageDeriveKey); if (UNLIKELY(result == nullptr)) { throwException(globalObject, scope, createTypeError(globalObject, "Invalid X25519 public key"_s)); return {}; @@ -1076,12 +1078,12 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPublicKey, (JSC::JSGlobalObject * glob auto impl = result.releaseNonNull(); return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); } else if (pKeyID == EVP_PKEY_X25519) { - auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, Vector(std::span { (uint8_t*)pem.der_data, (size_t)pem.der_len }), true, CryptoKeyUsageVerify); + auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::X25519, CryptoKeyOKP::NamedCurve::X25519, Vector(std::span { (uint8_t*)pem.der_data, (size_t)pem.der_len }), true, CryptoKeyUsageDeriveKey); if (pem.der_data) { OPENSSL_clear_free(pem.der_data, pem.der_len); } if (UNLIKELY(result == nullptr)) { - throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + throwException(globalObject, scope, createTypeError(globalObject, "Invalid X25519 public key"_s)); return {}; } auto impl = result.releaseNonNull(); @@ -1196,9 +1198,9 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createPublicKey, (JSC::JSGlobalObject * glob auto impl = result.releaseNonNull(); return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); } else if (pKeyID == EVP_PKEY_X25519) { - auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, Vector(std::span { (uint8_t*)data, byteLength }), true, CryptoKeyUsageVerify); + auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::X25519, CryptoKeyOKP::NamedCurve::X25519, Vector(std::span { (uint8_t*)data, byteLength }), true, CryptoKeyUsageDeriveKey); if (UNLIKELY(result == nullptr)) { - throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + throwException(globalObject, scope, createTypeError(globalObject, "Invalid X25519 public key"_s)); return {}; } auto impl = result.releaseNonNull(); @@ -1256,7 +1258,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__createSecretKey, (JSC::JSGlobalObject * lexi { ncrypto::ClearErrorOnReturn clearErrorOnReturn; JSValue bufferArg = callFrame->uncheckedArgument(0); - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); auto* structure = globalObject->JSCryptoKeyStructure(); @@ -1372,7 +1374,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__Sign, (JSC::JSGlobalObject * globalObject, J { ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count < 3) { @@ -1582,7 +1584,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__Verify, (JSC::JSGlobalObject * globalObject, { ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count < 4) { @@ -1810,7 +1812,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__Exports, (JSC::JSGlobalObject * globalObject { ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count < 2) { @@ -2396,7 +2398,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject_AsymmetricKeyDetails, (JSC::JSGlobalObject * ncrypto::ClearErrorOnReturn clearErrorOnReturn; if (auto* key = jsDynamicCast(callFrame->argument(0))) { auto id = key->wrapped().algorithmIdentifier(); - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); switch (id) { case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: @@ -2502,11 +2504,15 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject_AsymmetricKeyDetails, (JSC::JSGlobalObject * obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "namedCurve"_s)), JSC::jsString(vm, named_curve), 0); return JSC::JSValue::encode(obj); } + case CryptoAlgorithmIdentifier::X25519: case CryptoAlgorithmIdentifier::Ed25519: { auto* obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 1); auto& wrapped = key->wrapped(); const auto& okp = downcast(wrapped); - obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "namedCurve"_s)), JSC::jsString(vm, okp.namedCurveString()), 0); + auto* globalObject = defaultGlobalObject(lexicalGlobalObject); + auto& commonStrings = globalObject->commonStrings(); + JSString* namedCurveString = okp.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? commonStrings.x25519String(lexicalGlobalObject) : commonStrings.ed25519String(lexicalGlobalObject); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "namedCurve"_s)), namedCurveString, 0); return JSC::JSValue::encode(obj); } default: @@ -2520,7 +2526,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__generateKeyPairSync, (JSC::JSGlobalObject * { ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count < 1) { @@ -2722,7 +2728,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__generateKeyPairSync, (JSC::JSGlobalObject * obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "privateKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.privateKey.releaseNonNull()), 0); return JSValue::encode(obj); } else if (type_str == "x25519"_s) { - auto result = CryptoKeyOKP::generatePair(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, true, CryptoKeyUsageSign | CryptoKeyUsageVerify); + auto result = CryptoKeyOKP::generatePair(CryptoAlgorithmIdentifier::X25519, CryptoKeyOKP::NamedCurve::X25519, true, CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageSign | CryptoKeyUsageVerify); if (result.hasException()) { WebCore::propagateException(*lexicalGlobalObject, scope, result.releaseException()); return JSC::JSValue::encode(JSC::JSValue {}); @@ -2742,7 +2748,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__generateKeySync, (JSC::JSGlobalObject * lexi { ncrypto::ClearErrorOnReturn clearErrorOnReturn; auto count = callFrame->argumentCount(); - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count < 2) { JSC::throwTypeError(lexicalGlobalObject, scope, "generateKeySync requires 2 arguments"_s); @@ -2802,13 +2808,8 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__generateKeySync, (JSC::JSGlobalObject * lexi JSC_DEFINE_HOST_FUNCTION(KeyObject__AsymmetricKeyType, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { ncrypto::ClearErrorOnReturn clearErrorOnReturn; - static const NeverDestroyed values[] = { - MAKE_STATIC_STRING_IMPL("rsa"), - MAKE_STATIC_STRING_IMPL("rsa-pss"), - MAKE_STATIC_STRING_IMPL("ec"), - MAKE_STATIC_STRING_IMPL("x25519"), - MAKE_STATIC_STRING_IMPL("ed25519"), - }; + auto* globalObject = defaultGlobalObject(lexicalGlobalObject); + auto& commonStrings = globalObject->commonStrings(); // TODO: Look into DSA and DH if (auto* key = jsDynamicCast(callFrame->argument(0))) { @@ -2817,16 +2818,16 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__AsymmetricKeyType, (JSC::JSGlobalObject * le case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: case CryptoAlgorithmIdentifier::RSA_OAEP: - return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), values[0])); + return JSC::JSValue::encode(commonStrings.rsaString(globalObject)); case CryptoAlgorithmIdentifier::RSA_PSS: - return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), values[1])); + return JSC::JSValue::encode(commonStrings.rsaPssString(globalObject)); case CryptoAlgorithmIdentifier::ECDSA: case CryptoAlgorithmIdentifier::ECDH: - return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), values[2])); - case CryptoAlgorithmIdentifier::Ed25519: { + return JSC::JSValue::encode(commonStrings.ecString(globalObject)); + case CryptoAlgorithmIdentifier::Ed25519: + case CryptoAlgorithmIdentifier::X25519: { const auto& okpKey = downcast(key->wrapped()); - // TODO: CHECK THIS WHEN X488 AND ED448 ARE ADDED - return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), String(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? values[3] : values[4]))); + return JSC::JSValue::encode(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? commonStrings.x25519String(globalObject) : commonStrings.ed25519String(globalObject)); } default: return JSC::JSValue::encode(JSC::jsUndefined()); @@ -2881,6 +2882,7 @@ AsymmetricKeyValue::AsymmetricKeyValue(WebCore::CryptoKey& cryptoKey) case CryptoAlgorithmIdentifier::ECDH: key = downcast(cryptoKey).platformKey(); break; + case CryptoAlgorithmIdentifier::X25519: case CryptoAlgorithmIdentifier::Ed25519: { const auto& okpKey = downcast(cryptoKey); auto keyData = okpKey.exportKey(); @@ -2942,7 +2944,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__Equals, (JSC::JSGlobalObject * lexicalGlobal int ok = !first.key || !second.key ? -2 : EVP_PKEY_cmp(first.key, second.key); if (ok == -2) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "ERR_CRYPTO_UNSUPPORTED_OPERATION"_s)); return {}; @@ -2996,7 +2998,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__SymmetricKeySize, (JSC::JSGlobalObject * glo static EncodedJSValue doAsymmetricCipher(JSGlobalObject* globalObject, CallFrame* callFrame, bool encrypt) { auto count = callFrame->argumentCount(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (count != 2) { @@ -3138,7 +3140,7 @@ JSC_DEFINE_HOST_FUNCTION(KeyObject__privateDecrypt, (JSGlobalObject * globalObje static EncodedJSValue doAsymmetricSign(JSGlobalObject* globalObject, CallFrame* callFrame, bool encrypt) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() != 3) { diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index bd91fce4a5f8f3..fef63d1cca579e 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -1,4 +1,5 @@ #include "root.h" + #include "headers-handwritten.h" #include "JavaScriptCore/JSGlobalObject.h" #include "ModuleLoader.h" @@ -35,7 +36,7 @@ #include "NativeModuleImpl.h" #include "../modules/ObjectModule.h" -#include "wtf/Assertions.h" +#include "CommonJSModuleRecord.h" namespace Bun { using namespace JSC; @@ -64,7 +65,7 @@ extern "C" BunLoaderType Bun__getDefaultLoader(JSC::JSGlobalObject*, BunString* static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); auto scope = DECLARE_THROW_SCOPE(vm); scope.throwException(globalObject, value); @@ -73,7 +74,7 @@ static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* glob static JSC::JSInternalPromise* resolvedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast(JSC::JSPromise::Status::Fulfilled))); @@ -87,7 +88,7 @@ static JSC::SyntheticSourceProvider::SyntheticSourceGenerator generateInternalMo JSC::Identifier moduleKey, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) -> void { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); GlobalObject* globalObject = jsCast(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -128,7 +129,7 @@ static OnLoadResult handleOnLoadObjectResult(Zig::GlobalObject* globalObject, JS { OnLoadResult result {}; result.type = OnLoadResultTypeObject; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto& builtinNames = WebCore::builtinNames(vm); if (JSC::JSValue exportsValue = object->getIfPropertyExists(globalObject, builtinNames.exportsPublicName())) { if (exportsValue.isObject()) { @@ -198,7 +199,7 @@ OnLoadResult handleOnLoadResultNotPromise(Zig::GlobalObject* globalObject, JSC:: { OnLoadResult result = {}; result.type = OnLoadResultTypeError; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); result.value.error = JSC::jsUndefined(); auto scope = DECLARE_THROW_SCOPE(vm); BunLoaderType loader = Bun__getDefaultLoader(globalObject, specifier); @@ -302,10 +303,11 @@ static JSValue handleVirtualModuleResult( ErrorableResolvedSource* res, BunString* specifier, BunString* referrer, - bool wasModuleMock = false) + bool wasModuleMock = false, + JSCommonJSModule* commonJSModule = nullptr) { auto onLoadResult = handleOnLoadResult(globalObject, virtualModuleResult, specifier, wasModuleMock); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); ResolvedSourceCodeHolder sourceCodeHolder(res); @@ -364,6 +366,21 @@ static JSValue handleVirtualModuleResult( case OnLoadResultTypeObject: { JSC::JSObject* object = onLoadResult.value.object.getObject(); + if (commonJSModule) { + const auto& __esModuleIdentifier = vm.propertyNames->__esModule; + JSValue esModuleValue = object->getIfPropertyExists(globalObject, __esModuleIdentifier); + RETURN_IF_EXCEPTION(scope, {}); + if (esModuleValue && esModuleValue.toBoolean(globalObject)) { + JSValue defaultValue = object->getIfPropertyExists(globalObject, vm.propertyNames->defaultKeyword); + RETURN_IF_EXCEPTION(scope, {}); + if (defaultValue && !defaultValue.isUndefined()) { + commonJSModule->setExportsObject(defaultValue); + commonJSModule->hasEvaluated = true; + return commonJSModule; + } + } + } + JSC::ensureStillAliveHere(object); auto function = generateObjectModuleSourceCode( globalObject, @@ -408,7 +425,7 @@ extern "C" void Bun__onFulfillAsyncModule( BunString* referrer) { ResolvedSourceCodeHolder sourceCodeHolder(res); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSInternalPromise* promise = jsCast(JSC::JSValue::decode(encodedPromiseValue)); @@ -464,7 +481,7 @@ JSValue fetchCommonJSModule( BunString* typeAttribute) { void* bunVM = globalObject->bunVM(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); ErrorableResolvedSource resValue; memset(&resValue, 0, sizeof(ErrorableResolvedSource)); @@ -479,7 +496,14 @@ JSValue fetchCommonJSModule( // This is important for being able to trivially mock things like the filesystem. if (isBunTest) { if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock)) { - JSPromise* promise = jsCast(handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock)); + JSValue promiseOrCommonJSModule = handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock, target); + RETURN_IF_EXCEPTION(scope, {}); + + // If we assigned module.exports to the virtual module, we're done here. + if (promiseOrCommonJSModule == target) { + RELEASE_AND_RETURN(scope, target); + } + JSPromise* promise = jsCast(promiseOrCommonJSModule); switch (promise->status(vm)) { case JSPromise::Status::Rejected: { uint32_t promiseFlags = promise->internalField(JSPromise::Field::Flags).get().asUInt32AsAnyInt(); @@ -515,11 +539,19 @@ JSValue fetchCommonJSModule( auto tag = res->result.value.tag; switch (tag) { + // require("bun") + case SyntheticModuleType::BunObject: { + target->setExportsObject(globalObject->bunObject()); + target->hasEvaluated = true; + RELEASE_AND_RETURN(scope, target); + } + // require("module"), require("node:module") case SyntheticModuleType::NodeModule: { target->setExportsObject(globalObject->m_nodeModuleConstructor.getInitializedOnMainThread(globalObject)); target->hasEvaluated = true; RELEASE_AND_RETURN(scope, target); } + // require("process"), require("node:process") case SyntheticModuleType::NodeProcess: { target->setExportsObject(globalObject->processObject()); target->hasEvaluated = true; @@ -561,7 +593,14 @@ JSValue fetchCommonJSModule( // When "bun test" is NOT enabled, disable users from overriding builtin modules if (!isBunTest) { if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock)) { - JSPromise* promise = jsCast(handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock)); + JSValue promiseOrCommonJSModule = handleVirtualModuleResult(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock, target); + RETURN_IF_EXCEPTION(scope, {}); + + // If we assigned module.exports to the virtual module, we're done here. + if (promiseOrCommonJSModule == target) { + RELEASE_AND_RETURN(scope, target); + } + JSPromise* promise = jsCast(promiseOrCommonJSModule); switch (promise->status(vm)) { case JSPromise::Status::Rejected: { uint32_t promiseFlags = promise->internalField(JSPromise::Field::Flags).get().asUInt32AsAnyInt(); @@ -672,7 +711,7 @@ static JSValue fetchESMSourceCode( BunString* typeAttribute) { void* bunVM = globalObject->bunVM(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); ResolvedSourceCodeHolder sourceCodeHolder(res); @@ -901,7 +940,7 @@ using namespace Bun; BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultResolve, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ErrorableResolvedSource res = {}; res.success = false; JSC::JSValue objectResult = callFrame->argument(0); @@ -939,7 +978,7 @@ BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultResolve, (JSC::JSGlobalObje BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultReject, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue reason = callFrame->argument(0); PendingVirtualModuleResult* pendingModule = JSC::jsCast(callFrame->argument(1)); pendingModule->internalField(0).set(vm, pendingModule, JSC::jsUndefined()); diff --git a/src/bun.js/bindings/NoOpForTesting.cpp b/src/bun.js/bindings/NoOpForTesting.cpp index 919cd5b5f8e3a8..7e77219b23647e 100644 --- a/src/bun.js/bindings/NoOpForTesting.cpp +++ b/src/bun.js/bindings/NoOpForTesting.cpp @@ -36,7 +36,7 @@ JSC_DEFINE_CUSTOM_SETTER(noop_setter, JSC::JSObject* createNoOpForTesting(JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* object = JSC::constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()); object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, String("function"_s)), 0, functionNoop, ImplementationVisibility::Public, JSC::NoIntrinsic, 0); object->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, String("callback"_s)), 0, functionCallback, ImplementationVisibility::Public, JSC::NoIntrinsic, 0); diff --git a/src/bun.js/bindings/NodeCrypto.cpp b/src/bun.js/bindings/NodeCrypto.cpp index 2d68321d377040..be7ec8b08fc8ae 100644 --- a/src/bun.js/bindings/NodeCrypto.cpp +++ b/src/bun.js/bindings/NodeCrypto.cpp @@ -48,7 +48,7 @@ namespace WebCore { JSC_DEFINE_HOST_FUNCTION(jsStatelessDH, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 2) { @@ -84,11 +84,16 @@ JSC_DEFINE_HOST_FUNCTION(jsStatelessDH, (JSC::JSGlobalObject * lexicalGlobalObje // Use DHPointer::stateless to compute the shared secret auto secret = ncrypto::DHPointer::stateless(ourKeyPtr, theirKeyPtr).release(); + // These are owned by AsymmetricKeyValue, not by EVPKeyPointer. + ourKeyPtr.release(); + theirKeyPtr.release(); + auto buffer = ArrayBuffer::createFromBytes({ reinterpret_cast(secret.data), secret.len }, createSharedTask([](void* p) { OPENSSL_free(p); })); Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); auto* result = JSC::JSUint8Array::create(lexicalGlobalObject, globalObject->JSBufferSubclassStructure(), WTFMove(buffer), 0, secret.len); + RETURN_IF_EXCEPTION(scope, {}); if (!result) { return Bun::ERR::INVALID_ARG_VALUE(scope, lexicalGlobalObject, "diffieHellman"_s, jsUndefined(), "failed to allocate result buffer"_s); } @@ -98,7 +103,7 @@ JSC_DEFINE_HOST_FUNCTION(jsStatelessDH, (JSC::JSGlobalObject * lexicalGlobalObje JSC_DEFINE_HOST_FUNCTION(jsECDHConvertKey, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); ncrypto::ClearErrorOnReturn clearErrorOnReturn; @@ -156,7 +161,7 @@ JSC_DEFINE_HOST_FUNCTION(jsECDHConvertKey, (JSC::JSGlobalObject * lexicalGlobalO JSC_DEFINE_HOST_FUNCTION(jsGetCurves, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); const size_t numCurves = EC_get_builtin_curves(nullptr, 0); @@ -179,7 +184,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGetCurves, (JSC::JSGlobalObject * lexicalGlobalObject JSC_DEFINE_HOST_FUNCTION(jsGetCiphers, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); ncrypto::MarkPopErrorOnReturn mark_pop_error_on_return; @@ -223,7 +228,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGetCiphers, (JSC::JSGlobalObject * lexicalGlobalObjec JSC_DEFINE_HOST_FUNCTION(jsCertVerifySpkac, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto input = KeyObject__GetBuffer(callFrame->argument(0)); @@ -242,7 +247,7 @@ JSC_DEFINE_HOST_FUNCTION(jsCertVerifySpkac, (JSC::JSGlobalObject * lexicalGlobal JSC_DEFINE_HOST_FUNCTION(jsCertExportPublicKey, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto input = KeyObject__GetBuffer(callFrame->argument(0)); @@ -271,7 +276,7 @@ JSC_DEFINE_HOST_FUNCTION(jsCertExportPublicKey, (JSC::JSGlobalObject * lexicalGl JSC_DEFINE_HOST_FUNCTION(jsCertExportChallenge, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto input = KeyObject__GetBuffer(callFrame->argument(0)); @@ -301,7 +306,7 @@ JSC_DEFINE_HOST_FUNCTION(jsCertExportChallenge, (JSC::JSGlobalObject * lexicalGl JSC_DEFINE_HOST_FUNCTION(jsGetCipherInfo, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); ncrypto::MarkPopErrorOnReturn mark_pop_error_on_return; diff --git a/src/bun.js/bindings/NodeDirent.cpp b/src/bun.js/bindings/NodeDirent.cpp new file mode 100644 index 00000000000000..043d09e617c2c9 --- /dev/null +++ b/src/bun.js/bindings/NodeDirent.cpp @@ -0,0 +1,372 @@ +#include "ErrorCode.h" +#include "headers-handwritten.h" +#include "root.h" + +#include "JavaScriptCore/FunctionPrototype.h" +#include "JavaScriptCore/LazyClassStructure.h" +#include "JavaScriptCore/LazyClassStructureInlines.h" +#include "JavaScriptCore/VMTrapsInlines.h" +#include "BunBuiltinNames.h" +#include "JavaScriptCore/ArgList.h" +#include "JavaScriptCore/JSType.h" +#include "JavaScriptCore/ObjectInitializationScope.h" + +#include "JavaScriptCore/ObjectConstructor.h" +#include +#include +#include +#include +#include +#include +#include +#include "ZigGlobalObject.h" + +namespace Bun { + +using namespace JSC; +using namespace WebCore; + +JSC_DECLARE_HOST_FUNCTION(callDirent); +JSC_DECLARE_HOST_FUNCTION(constructDirent); + +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsBlockDevice); +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsCharacterDevice); +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsDirectory); +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsFIFO); +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsFile); +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsSocket); +static JSC_DECLARE_HOST_FUNCTION(jsDirentProtoFuncIsSymbolicLink); + +static const HashTableValue JSDirentPrototypeTableValues[] = { + { "isBlockDevice"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsBlockDevice, 0 } }, + { "isCharacterDevice"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsCharacterDevice, 0 } }, + { "isDirectory"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsDirectory, 0 } }, + { "isFIFO"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsFIFO, 0 } }, + { "isFile"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsFile, 0 } }, + { "isSocket"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsSocket, 0 } }, + { "isSymbolicLink"_s, static_cast(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDirentProtoFuncIsSymbolicLink, 0 } }, +}; + +static Structure* getStructure(Zig::GlobalObject* globalObject) +{ + return globalObject->m_JSDirentClassStructure.get(globalObject); +} + +// Prototype class +class JSDirentPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSDirentPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSDirentPrototype* prototype = new (NotNull, JSC::allocateCell(vm)) JSDirentPrototype(vm, structure); + prototype->finishCreation(vm); + return prototype; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.plainObjectSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + auto* structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + structure->setMayBePrototype(true); + return structure; + } + +private: + JSDirentPrototype(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM& vm) + { + Base::finishCreation(vm); + reifyStaticProperties(vm, JSDirentPrototype::info(), JSDirentPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); + } +}; + +// Constructor class +class JSDirentConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSDirentConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* prototype) + { + JSDirentConstructor* constructor = new (NotNull, JSC::allocateCell(vm)) JSDirentConstructor(vm, structure); + constructor->finishCreation(vm, prototype); + return constructor; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.internalFunctionSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + +private: + JSDirentConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, callDirent, constructDirent) + { + } + + void finishCreation(JSC::VM& vm, JSC::JSObject* prototype) + { + Base::finishCreation(vm, 3, "Dirent"_s); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + } +}; + +JSC::Structure* createJSDirentObjectStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + auto* prototype = JSDirentPrototype::create(vm, globalObject, JSDirentPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::FinalObjectType, 0), JSFinalObject::info(), NonArray, 4); + + // Add property transitions for all dirent fields + PropertyOffset offset = 0; + structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->name, 0, offset); + structure = structure->addPropertyTransition(vm, structure, Bun::builtinNames(vm).pathPublicName(), 0, offset); + structure = structure->addPropertyTransition(vm, structure, Bun::builtinNames(vm).dataPrivateName(), 0, offset); + structure = structure->addPropertyTransition(vm, structure, Identifier::fromString(vm, "parentPath"_s), 0, offset); + + return structure; +} + +JSC_DEFINE_HOST_FUNCTION(callDirent, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + return Bun::throwError(globalObject, scope, ErrorCode::ERR_ILLEGAL_CONSTRUCTOR, "Dirent constructor cannot be called as a function"_s); +} + +JSC_DEFINE_HOST_FUNCTION(constructDirent, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue name = callFrame->argument(0); + JSValue type = callFrame->argument(1); + JSValue path = callFrame->argument(2); + + auto* zigGlobalObject = defaultGlobalObject(globalObject); + Structure* structure = zigGlobalObject->m_JSDirentClassStructure.get(zigGlobalObject); + auto* originalStructure = structure; + JSValue newTarget = callFrame->newTarget(); + if (UNLIKELY(zigGlobalObject->m_JSDirentClassStructure.constructor(zigGlobalObject) != newTarget)) { + auto scope = DECLARE_THROW_SCOPE(vm); + if (!newTarget) { + throwTypeError(globalObject, scope, "Class constructor Dirent cannot be invoked without 'new'"_s); + return {}; + } + + auto* functionGlobalObject = defaultGlobalObject(getFunctionRealm(globalObject, newTarget.getObject())); + RETURN_IF_EXCEPTION(scope, {}); + structure = InternalFunction::createSubclassStructure( + globalObject, newTarget.getObject(), functionGlobalObject->m_JSDirentClassStructure.get(functionGlobalObject)); + scope.release(); + } + + auto* object = JSC::JSFinalObject::create(vm, structure); + if (structure->id() != originalStructure->id()) { + object->putDirect(vm, vm.propertyNames->name, name, 0); + object->putDirect(vm, Bun::builtinNames(vm).pathPublicName(), path, 0); + object->putDirect(vm, Bun::builtinNames(vm).dataPrivateName(), type, 0); + object->putDirect(vm, Identifier::fromString(vm, "parentPath"_s), path, 0); + } else { + object->putDirectOffset(vm, 0, name); + object->putDirectOffset(vm, 1, path); + object->putDirectOffset(vm, 2, type); + object->putDirectOffset(vm, 3, path); + } + + return JSValue::encode(object); +} + +static inline int32_t getType(JSC::VM& vm, JSValue value, Zig::GlobalObject* globalObject) +{ + JSObject* object = value.getObject(); + if (UNLIKELY(!object)) { + return std::numeric_limits::max(); + } + auto* structure = getStructure(globalObject); + JSValue type; + if (structure->id() != object->structure()->id()) { + type = object->get(globalObject, Bun::builtinNames(vm).dataPrivateName()); + if (UNLIKELY(!type)) { + return std::numeric_limits::max(); + } + } else { + type = object->getDirect(2); + } + + if (type.isAnyInt()) { + return type.toInt32(globalObject); + } + + return std::numeric_limits::max(); +} + +enum class DirEntType : int32_t { + // These have to match up with uv_dirent_type_t + Unknown = 0, + File = 1, + Directory = 2, + SymLink = 3, + NamedPipe = 4, + UnixDomainSocket = 5, + CharacterDevice = 6, + BlockDevice = 7, + Whiteout = 0, + Door = 0, + EventPort = 0 +}; + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsBlockDevice, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::BlockDevice))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsCharacterDevice, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::CharacterDevice))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsDirectory, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::Directory))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsFIFO, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::NamedPipe) || type == static_cast(DirEntType::EventPort))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsFile, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::File))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsSocket, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::UnixDomainSocket))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDirentProtoFuncIsSymbolicLink, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + int32_t type = getType(vm, callFrame->thisValue(), defaultGlobalObject(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); + + return JSValue::encode(jsBoolean(type == static_cast(DirEntType::SymLink))); +} + +void initJSDirentClassStructure(JSC::LazyClassStructure::Initializer& init) +{ + auto* structure = createJSDirentObjectStructure(init.vm, init.global); + auto* prototype = structure->storedPrototypeObject(); + auto* constructor = JSDirentConstructor::create(init.vm, JSDirentConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); + init.setPrototype(prototype); + init.setStructure(structure); + init.setConstructor(constructor); +} + +extern "C" JSC::EncodedJSValue Bun__JSDirentObjectConstructor(Zig::GlobalObject* globalobject) +{ + return JSValue::encode(globalobject->m_JSDirentClassStructure.constructor(globalobject)); +} + +extern "C" JSC::EncodedJSValue Bun__Dirent__toJS(Zig::GlobalObject* globalObject, int type, BunString* name, BunString* path, JSString** previousPath) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* structure = globalObject->m_JSDirentClassStructure.get(globalObject); + auto* object = JSC::JSFinalObject::create(vm, structure); + JSString* pathValue = nullptr; + if (path && path->tag == BunStringTag::WTFStringImpl && previousPath && *previousPath && (*previousPath)->length() == path->impl.wtf->length()) { + auto view = (*previousPath)->view(globalObject); + if (view == path->impl.wtf) { + pathValue = *previousPath; + + // Decrement the ref count of the previous path + auto pathString = path->transferToWTFString(); + } + } + + if (!pathValue) { + auto pathString = path->transferToWTFString(); + pathValue = jsString(vm, WTFMove(pathString)); + if (previousPath) { + *previousPath = pathValue; + } + } + + auto nameString = name->transferToWTFString(); + auto nameValue = jsString(vm, WTFMove(nameString)); + auto typeValue = jsNumber(type); + object->putDirectOffset(vm, 0, nameValue); + object->putDirectOffset(vm, 1, pathValue); + object->putDirectOffset(vm, 2, typeValue); + object->putDirectOffset(vm, 3, pathValue); + + return JSValue::encode(object); +} + +const ClassInfo JSDirentPrototype::s_info = { "Dirent"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDirentPrototype) }; +const ClassInfo JSDirentConstructor::s_info = { "Dirent"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDirentConstructor) }; + +} // namespace Bun diff --git a/src/bun.js/bindings/NodeDirent.h b/src/bun.js/bindings/NodeDirent.h new file mode 100644 index 00000000000000..6cfcf5bdf0c7a3 --- /dev/null +++ b/src/bun.js/bindings/NodeDirent.h @@ -0,0 +1,9 @@ +#pragma once + +#include "JavaScriptCore/LazyClassStructure.h" + +namespace Bun { + +void initJSDirentClassStructure(JSC::LazyClassStructure::Initializer& init); + +} // namespace Bun diff --git a/src/bun.js/bindings/NodeFSBinding.cpp b/src/bun.js/bindings/NodeFSBinding.cpp new file mode 100644 index 00000000000000..d818b610e6926f --- /dev/null +++ b/src/bun.js/bindings/NodeFSBinding.cpp @@ -0,0 +1,928 @@ + +#include "root.h" + +#include "JavaScriptCore/FunctionPrototype.h" +#include "JavaScriptCore/LazyClassStructure.h" +#include "JavaScriptCore/LazyClassStructureInlines.h" +#include "JavaScriptCore/VMTrapsInlines.h" +#include "BunBuiltinNames.h" +#include "JavaScriptCore/ArgList.h" +#include "JavaScriptCore/JSType.h" +#include "JavaScriptCore/ObjectInitializationScope.h" + +#include "JavaScriptCore/ObjectConstructor.h" +#include +#include +#include +#include +#include +#include +#include +#include "ZigGlobalObject.h" +#include "JavaScriptCore/DateInstance.h" +namespace Bun { + +class JSStatsPrototype; +class JSBigIntStatsPrototype; +class JSStatsConstructor; +class JSBigIntStatsConstructor; +using namespace JSC; +using namespace WebCore; + +#if !OS(WINDOWS) +#include +#else +#ifndef mode_t +#define mode_t int32_t +#endif + +#ifndef S_IFMT +#define S_IFMT 0170000 +#endif + +#ifndef S_IFDIR +#define S_IFDIR 0040000 +#endif + +#ifndef S_IFCHR +#define S_IFCHR 0020000 +#endif + +#ifndef S_IFBLK +#define S_IFBLK 0060000 +#endif + +#ifndef S_IFREG +#define S_IFREG 0100000 +#endif + +#ifndef S_IFIFO +#define S_IFIFO 0010000 +#endif + +#ifndef S_IFLNK +#define S_IFLNK 0120000 +#endif + +#ifndef S_IFSOCK +#define S_IFSOCK 0140000 +#endif + +#ifndef S_ISBLK +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* block special */ +#endif +#ifndef S_ISCHR +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* char special */ +#endif +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* directory */ +#endif +#ifndef S_ISFIFO +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* fifo or socket */ +#endif +#ifndef S_ISREG +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* regular file */ +#endif +#ifndef S_ISLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* symbolic link */ +#endif +#ifndef S_ISSOCK +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* socket */ +#endif +#endif + +JSC_DECLARE_HOST_FUNCTION(callStats); +JSC_DECLARE_HOST_FUNCTION(callBigIntStats); +JSC_DECLARE_HOST_FUNCTION(constructStats); +JSC_DECLARE_HOST_FUNCTION(constructBigIntStats); + +enum class StatFunction { + isBlockDevice, + isCharacterDevice, + isDirectory, + isFIFO, + isFile, + isSocket, + isSymbolicLink, +}; + +static bool isModeFn(StatFunction fn, mode_t mode) +{ + switch (fn) { + case StatFunction::isBlockDevice: + return S_ISBLK(mode); + case StatFunction::isCharacterDevice: + return S_ISCHR(mode); + case StatFunction::isDirectory: + return S_ISDIR(mode); + case StatFunction::isFIFO: + return S_ISFIFO(mode); + case StatFunction::isFile: + return S_ISREG(mode); + case StatFunction::isSocket: + return S_ISSOCK(mode); + case StatFunction::isSymbolicLink: + return S_ISLNK(mode); + default: { + ASSERT_NOT_REACHED(); + } + } +} + +template +static JSValue modeStatFunction(JSC::JSGlobalObject* globalObject, CallFrame* callFrame) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + auto* thisObject = JSC::jsDynamicCast(callFrame->thisValue()); + if (!thisObject) + return JSC::jsUndefined(); + + JSValue modeValue = thisObject->get(globalObject, builtinNames(vm).modePublicName()); + RETURN_IF_EXCEPTION(scope, {}); + + if constexpr (isBigInt) { + int64_t mode_value = modeValue.toBigInt64(globalObject); + return jsBoolean(isModeFn(statFunction, mode_value)); + } + + mode_t mode = modeValue.toInt32(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + return jsBoolean(isModeFn(statFunction, mode)); +} + +template +Structure* getStructure(Zig::GlobalObject* globalObject) +{ + if (isBigInt) { + return globalObject->m_JSStatsBigIntClassStructure.getInitializedOnMainThread(globalObject); + } + + return globalObject->m_JSStatsClassStructure.getInitializedOnMainThread(globalObject); +} + +template +JSObject* getPrototype(Zig::GlobalObject* globalObject) +{ + if (isBigInt) { + return globalObject->m_JSStatsBigIntClassStructure.prototypeInitializedOnMainThread(globalObject); + } + + return globalObject->m_JSStatsClassStructure.prototypeInitializedOnMainThread(globalObject); +} + +template +JSObject* getConstructor(Zig::GlobalObject* globalObject) +{ + if (isBigInt) { + return globalObject->m_JSStatsBigIntClassStructure.constructorInitializedOnMainThread(globalObject); + } + + return globalObject->m_JSStatsClassStructure.constructorInitializedOnMainThread(globalObject); +} + +enum class DateFieldType : uint8_t { + atime = 10, + mtime = 11, + ctime = 12, + birthtime = 13, +}; + +static const Identifier& identifier(JSC::VM& vm, DateFieldType dateField) +{ + const auto& names = WebCore::builtinNames(vm); + switch (dateField) { + case DateFieldType::atime: + return names.atimeMsPublicName(); + case DateFieldType::mtime: + return names.mtimeMsPublicName(); + case DateFieldType::ctime: + return names.ctimeMsPublicName(); + case DateFieldType::birthtime: + return names.birthtimeMsPublicName(); + } + + ASSERT_NOT_REACHED(); +} + +template +inline JSC::JSValue getDateField(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSC::JSObject* thisObject = jsDynamicCast(JSC::JSValue::decode(thisValue)); + if (!thisObject) + return JSC::jsUndefined(); + + JSValue value; + if (thisObject->structureID() == getStructure(defaultGlobalObject(globalObject))->id()) { + value = thisObject->getDirect(static_cast(field)); + ASSERT(thisObject->getDirectOffset(vm, identifier(vm, field)) == static_cast(field)); + } else { + value = thisObject->get(globalObject, identifier(vm, field)); + RETURN_IF_EXCEPTION(scope, {}); + } + + double internalNumber = isBigInt ? value.toBigInt64(globalObject) : value.toNumber(globalObject); + RETURN_IF_EXCEPTION(scope, {}); + + JSValue result = JSC::DateInstance::create(vm, globalObject->dateStructure(), internalNumber); + if (!thisObject->structure()->mayBePrototype()) { + thisObject->putDirect(vm, propertyName, result, 0); + } + return result; +} + +JSC_DEFINE_CUSTOM_GETTER(jsStatsPrototypeGetter_atime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} +JSC_DEFINE_CUSTOM_GETTER(jsStatsPrototypeGetter_mtime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} +JSC_DEFINE_CUSTOM_GETTER(jsStatsPrototypeGetter_ctime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} +JSC_DEFINE_CUSTOM_GETTER(jsStatsPrototypeGetter_birthtime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} + +JSC_DEFINE_CUSTOM_GETTER(jsBigIntStatsPrototypeGetter_birthtime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} +JSC_DEFINE_CUSTOM_GETTER(jsBigIntStatsPrototypeGetter_ctime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} + +JSC_DEFINE_CUSTOM_GETTER(jsBigIntStatsPrototypeGetter_mtime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} + +JSC_DEFINE_CUSTOM_GETTER(jsBigIntStatsPrototypeGetter_atime, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName propertyName)) +{ + return JSValue::encode(getDateField(globalObject, thisValue, propertyName)); +} + +JSC_DEFINE_CUSTOM_SETTER(jsStatsPrototypeFunction_DatePutter, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, JSC::PropertyName propertyName)) +{ + auto& vm = globalObject->vm(); + JSObject* thisObject = jsDynamicCast(JSValue::decode(thisValue)); + if (!thisObject) + return false; + + thisObject->putDirect(vm, propertyName, JSValue::decode(encodedValue), 0); + return true; +} + +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isBlockDevice, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isCharacterDevice, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isDirectory, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isFIFO, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isFile, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isSocket, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsStatsPrototypeFunction_isSymbolicLink, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} + +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isBlockDevice, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isCharacterDevice, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isDirectory, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isFIFO, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isFile, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isSocket, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} +JSC_DEFINE_HOST_FUNCTION(jsBigIntStatsPrototypeFunction_isSymbolicLink, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return JSValue::encode(modeStatFunction(globalObject, callframe)); +} + +static const HashTableValue JSStatsPrototypeTableValues[] = { + { "isBlockDevice"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isBlockDevice, 0 } }, + { "isCharacterDevice"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isCharacterDevice, 0 } }, + { "isDirectory"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isDirectory, 0 } }, + { "isFIFO"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isFIFO, 0 } }, + { "isFile"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isFile, 0 } }, + { "isSocket"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isSocket, 0 } }, + { "isSymbolicLink"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsStatsPrototypeFunction_isSymbolicLink, 0 } }, + { "atime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsStatsPrototypeGetter_atime, jsStatsPrototypeFunction_DatePutter } }, + { "mtime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsStatsPrototypeGetter_mtime, jsStatsPrototypeFunction_DatePutter } }, + { "ctime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsStatsPrototypeGetter_ctime, jsStatsPrototypeFunction_DatePutter } }, + { "birthtime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsStatsPrototypeGetter_birthtime, jsStatsPrototypeFunction_DatePutter } }, +}; + +static const HashTableValue JSBigIntStatsPrototypeTableValues[] = { + { "isBlockDevice"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isBlockDevice, 0 } }, + { "isCharacterDevice"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isCharacterDevice, 0 } }, + { "isDirectory"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isDirectory, 0 } }, + { "isFIFO"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isFIFO, 0 } }, + { "isFile"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isFile, 0 } }, + { "isSocket"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isSocket, 0 } }, + { "isSymbolicLink"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBigIntStatsPrototypeFunction_isSymbolicLink, 0 } }, + { "atime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsBigIntStatsPrototypeGetter_atime, jsStatsPrototypeFunction_DatePutter } }, + { "mtime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsBigIntStatsPrototypeGetter_mtime, jsStatsPrototypeFunction_DatePutter } }, + { "ctime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsBigIntStatsPrototypeGetter_ctime, jsStatsPrototypeFunction_DatePutter } }, + { "birthtime"_s, static_cast(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsBigIntStatsPrototypeGetter_birthtime, jsStatsPrototypeFunction_DatePutter } }, +}; + +class JSStatsPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSStatsPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSStatsPrototype* prototype = new (NotNull, JSC::allocateCell(vm)) JSStatsPrototype(vm, structure); + prototype->finishCreation(vm); + return prototype; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStatsPrototype, Base); + return &vm.plainObjectSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + auto* structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + structure->setMayBePrototype(true); + return structure; + } + +private: + JSStatsPrototype(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM& vm) + { + Base::finishCreation(vm); + ASSERT(inherits(info())); + + reifyStaticProperties(vm, this->classInfo(), JSStatsPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); + } +}; + +class JSBigIntStatsPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSBigIntStatsPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSBigIntStatsPrototype* prototype = new (NotNull, JSC::allocateCell(vm)) JSBigIntStatsPrototype(vm, structure); + prototype->finishCreation(vm); + return prototype; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBigIntStatsPrototype, Base); + return &vm.plainObjectSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + auto* structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + structure->setMayBePrototype(true); + return structure; + } + +private: + JSBigIntStatsPrototype(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM& vm) + { + Base::finishCreation(vm); + ASSERT(inherits(info())); + + reifyStaticProperties(vm, this->classInfo(), JSBigIntStatsPrototypeTableValues, *this); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); + } +}; + +class JSStatsConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSStatsConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* prototype) + { + JSStatsConstructor* constructor = new (NotNull, JSC::allocateCell(vm)) JSStatsConstructor(vm, structure); + constructor->finishCreation(vm, prototype); + return constructor; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.internalFunctionSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + +private: + JSStatsConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, callStats, constructStats) + { + } + + void finishCreation(JSC::VM& vm, JSC::JSObject* prototype) + { + Base::finishCreation(vm, 0, "Stats"_s); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + } +}; + +class JSBigIntStatsConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static constexpr unsigned StructureFlags = Base::StructureFlags; + + static JSBigIntStatsConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSC::JSObject* prototype) + { + JSBigIntStatsConstructor* constructor = new (NotNull, JSC::allocateCell(vm)) JSBigIntStatsConstructor(vm, structure); + constructor->finishCreation(vm, prototype); + return constructor; + } + + DECLARE_INFO; + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + return &vm.internalFunctionSpace(); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + +private: + JSBigIntStatsConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, callBigIntStats, constructBigIntStats) + { + } + + void finishCreation(JSC::VM& vm, JSC::JSObject* prototype) + { + Base::finishCreation(vm, 0, "BigIntStats"_s); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + } +}; + +JSC::Structure* createJSStatsObjectStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + auto* prototype = JSStatsPrototype::create(vm, globalObject, JSStatsPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::FinalObjectType, 0), JSFinalObject::info(), NonArray, + 14); + + // Add property transitions for all stat fields + PropertyOffset offset = 0; + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "dev"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "ino"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "mode"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "nlink"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "uid"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "gid"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "rdev"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "size"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "blksize"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "blocks"_s), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::atime)); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "atimeMs"_s), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::mtime)); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "mtimeMs"_s), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::ctime)); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "ctimeMs"_s), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::birthtime)); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "birthtimeMs"_s), 0, offset); + + return structure; +} + +JSC::Structure* createJSBigIntStatsObjectStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + auto prototype = JSBigIntStatsPrototype::create(vm, globalObject, JSBigIntStatsPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); + auto structure = JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::FinalObjectType, 0), JSFinalObject::info(), NonArray, + 18); + + // Add property transitions for all bigint stat fields + PropertyOffset offset = 0; + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "dev"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "ino"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "mode"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "nlink"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "uid"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "gid"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "rdev"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "size"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "blksize"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "blocks"_s), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::atime)); + structure = structure->addPropertyTransition(vm, structure, identifier(vm, DateFieldType::atime), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::mtime)); + structure = structure->addPropertyTransition(vm, structure, identifier(vm, DateFieldType::mtime), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::ctime)); + structure = structure->addPropertyTransition(vm, structure, identifier(vm, DateFieldType::ctime), 0, offset); + ASSERT(offset + 1 == static_cast(DateFieldType::birthtime)); + structure = structure->addPropertyTransition(vm, structure, identifier(vm, DateFieldType::birthtime), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "atimeNs"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "mtimeNs"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "ctimeNs"_s), 0, offset); + structure = structure->addPropertyTransition(vm, structure, JSC::Identifier::fromString(vm, "birthtimeNs"_s), 0, offset); + + return structure; +} + +extern "C" JSC::EncodedJSValue Bun__createJSStatsObject(Zig::GlobalObject* globalObject, int64_t dev, + int64_t ino, + int64_t mode, + int64_t nlink, + int64_t uid, int64_t gid, int64_t rdev, int64_t size, int64_t blksize, int64_t blocks, double atimeMs, double mtimeMs, double ctimeMs, double birthtimeMs) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSC::JSValue js_dev = JSC::jsDoubleNumber(dev); + JSC::JSValue js_ino = JSC::jsDoubleNumber(ino); + JSC::JSValue js_mode = JSC::jsDoubleNumber(mode); + JSC::JSValue js_nlink = JSC::jsDoubleNumber(nlink); + JSC::JSValue js_uid = JSC::jsDoubleNumber(uid); + JSC::JSValue js_gid = JSC::jsDoubleNumber(gid); + JSC::JSValue js_rdev = JSC::jsDoubleNumber(rdev); + JSC::JSValue js_size = JSC::jsDoubleNumber(size); + JSC::JSValue js_blksize = JSC::jsDoubleNumber(blksize); + JSC::JSValue js_blocks = JSC::jsDoubleNumber(blocks); + JSC::JSValue js_atimeMs = JSC::jsDoubleNumber(atimeMs); + JSC::JSValue js_mtimeMs = JSC::jsDoubleNumber(mtimeMs); + JSC::JSValue js_ctimeMs = JSC::jsDoubleNumber(ctimeMs); + JSC::JSValue js_birthtimeMs = JSC::jsDoubleNumber(birthtimeMs); + + auto* structure = getStructure(globalObject); + auto* object = JSC::JSFinalObject::create(vm, structure); + + object->putDirectOffset(vm, 0, js_dev); + object->putDirectOffset(vm, 1, js_ino); + object->putDirectOffset(vm, 2, js_mode); + object->putDirectOffset(vm, 3, js_nlink); + object->putDirectOffset(vm, 4, js_uid); + object->putDirectOffset(vm, 5, js_gid); + object->putDirectOffset(vm, 6, js_rdev); + object->putDirectOffset(vm, 7, js_size); + object->putDirectOffset(vm, 8, js_blksize); + object->putDirectOffset(vm, 9, js_blocks); + object->putDirectOffset(vm, 10, js_atimeMs); + object->putDirectOffset(vm, 11, js_mtimeMs); + object->putDirectOffset(vm, 12, js_ctimeMs); + object->putDirectOffset(vm, 13, js_birthtimeMs); + + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(object)); +} + +extern "C" JSC::EncodedJSValue Bun__createJSBigIntStatsObject(Zig::GlobalObject* globalObject, + int64_t dev, + int64_t ino, + int64_t mode, + int64_t nlink, + int64_t uid, + int64_t gid, + int64_t rdev, + int64_t size, + int64_t blksize, + int64_t blocks, + int64_t atimeMs, + int64_t mtimeMs, + int64_t ctimeMs, + int64_t birthtimeMs, + uint64_t atimeNs, + uint64_t mtimeNs, + uint64_t ctimeNs, + uint64_t birthtimeNs) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* structure = getStructure(globalObject); + JSC::JSValue js_dev = JSC::JSBigInt::createFrom(globalObject, dev); + JSC::JSValue js_ino = JSC::JSBigInt::createFrom(globalObject, ino); + JSC::JSValue js_mode = JSC::JSBigInt::createFrom(globalObject, mode); + JSC::JSValue js_nlink = JSC::JSBigInt::createFrom(globalObject, nlink); + JSC::JSValue js_uid = JSC::JSBigInt::createFrom(globalObject, uid); + JSC::JSValue js_gid = JSC::JSBigInt::createFrom(globalObject, gid); + JSC::JSValue js_rdev = JSC::JSBigInt::createFrom(globalObject, rdev); + JSC::JSValue js_size = JSC::JSBigInt::createFrom(globalObject, size); + JSC::JSValue js_blksize = JSC::JSBigInt::createFrom(globalObject, blksize); + JSC::JSValue js_blocks = JSC::JSBigInt::createFrom(globalObject, blocks); + JSC::JSValue js_atimeMs = JSC::JSBigInt::createFrom(globalObject, atimeMs); + JSC::JSValue js_mtimeMs = JSC::JSBigInt::createFrom(globalObject, mtimeMs); + JSC::JSValue js_ctimeMs = JSC::JSBigInt::createFrom(globalObject, ctimeMs); + JSC::JSValue js_birthtimeMs = JSC::JSBigInt::createFrom(globalObject, birthtimeMs); + JSC::JSValue js_atimeNs = JSC::JSBigInt::createFrom(globalObject, atimeNs); + JSC::JSValue js_mtimeNs = JSC::JSBigInt::createFrom(globalObject, mtimeNs); + JSC::JSValue js_ctimeNs = JSC::JSBigInt::createFrom(globalObject, ctimeNs); + JSC::JSValue js_birthtimeNs = JSC::JSBigInt::createFrom(globalObject, birthtimeNs); + auto* object = JSC::JSFinalObject::create(vm, structure); + + object->putDirectOffset(vm, 0, js_dev); + object->putDirectOffset(vm, 1, js_ino); + object->putDirectOffset(vm, 2, js_mode); + object->putDirectOffset(vm, 3, js_nlink); + object->putDirectOffset(vm, 4, js_uid); + object->putDirectOffset(vm, 5, js_gid); + object->putDirectOffset(vm, 6, js_rdev); + object->putDirectOffset(vm, 7, js_size); + object->putDirectOffset(vm, 8, js_blksize); + object->putDirectOffset(vm, 9, js_blocks); + object->putDirectOffset(vm, static_cast(DateFieldType::atime), js_atimeMs); + object->putDirectOffset(vm, static_cast(DateFieldType::mtime), js_mtimeMs); + object->putDirectOffset(vm, static_cast(DateFieldType::ctime), js_ctimeMs); + object->putDirectOffset(vm, static_cast(DateFieldType::birthtime), js_birthtimeMs); + object->putDirectOffset(vm, 14, js_atimeNs); + object->putDirectOffset(vm, 15, js_mtimeNs); + object->putDirectOffset(vm, 16, js_ctimeNs); + object->putDirectOffset(vm, 17, js_birthtimeNs); + + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(object)); +} + +const JSC::ClassInfo JSStatsPrototype::s_info = { "Stats"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStatsPrototype) }; +const JSC::ClassInfo JSBigIntStatsPrototype::s_info = { "BigIntStats"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBigIntStatsPrototype) }; +const JSC::ClassInfo JSStatsConstructor::s_info = { "Stats"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStatsConstructor) }; +const JSC::ClassInfo JSBigIntStatsConstructor::s_info = { "BigIntStats"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBigIntStatsConstructor) }; + +template +inline JSValue callJSStatsFunction(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + // function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, + // ino, size, blocks, + // atimeNs, mtimeNs, ctimeNs, birthtimeNs) { + + // function Stats(dev, mode, nlink, uid, gid, rdev, blksize, + // ino, size, blocks, + // atimeMs, mtimeMs, ctimeMs, birthtimeMs) { + auto* structure = getStructure(defaultGlobalObject(globalObject)); + + JSValue dev = callFrame->argument(0); + JSValue mode = callFrame->argument(1); + JSValue nlink = callFrame->argument(2); + JSValue uid = callFrame->argument(3); + JSValue gid = callFrame->argument(4); + JSValue rdev = callFrame->argument(5); + JSValue blksize = callFrame->argument(6); + JSValue ino = callFrame->argument(7); + JSValue size = callFrame->argument(8); + JSValue blocks = callFrame->argument(9); + JSValue atimeNs = callFrame->argument(10); + JSValue mtimeNs = callFrame->argument(11); + JSValue ctimeNs = callFrame->argument(12); + JSValue birthtimeNs = callFrame->argument(13); + + JSValue atimeMs = atimeNs; + JSValue mtimeMs = mtimeNs; + JSValue ctimeMs = ctimeNs; + JSValue birthtimeMs = birthtimeNs; + + if constexpr (isBigInt) { + // this.atimeMs = atimeNs / kNsPerMsBigInt; + // this.mtimeMs = mtimeNs / kNsPerMsBigInt; + // this.ctimeMs = ctimeNs / kNsPerMsBigInt; + // this.birthtimeMs = birthtimeNs / kNsPerMsBigInt; + const double kNsPerMsBigInt = 1000000; + atimeMs = jsDoubleNumber(atimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + mtimeMs = jsDoubleNumber(mtimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + ctimeMs = jsDoubleNumber(ctimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + birthtimeMs = jsDoubleNumber(birthtimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + } + + auto* object = JSC::JSFinalObject::create(vm, structure); + + object->putDirectOffset(vm, 0, dev); + object->putDirectOffset(vm, 1, mode); + object->putDirectOffset(vm, 2, nlink); + object->putDirectOffset(vm, 3, uid); + object->putDirectOffset(vm, 4, gid); + object->putDirectOffset(vm, 5, rdev); + object->putDirectOffset(vm, 6, blksize); + object->putDirectOffset(vm, 7, ino); + object->putDirectOffset(vm, 8, size); + object->putDirectOffset(vm, 9, blocks); + + object->putDirectOffset(vm, static_cast(DateFieldType::atime), atimeMs); + object->putDirectOffset(vm, static_cast(DateFieldType::mtime), mtimeMs); + object->putDirectOffset(vm, static_cast(DateFieldType::ctime), ctimeMs); + object->putDirectOffset(vm, static_cast(DateFieldType::birthtime), birthtimeMs); + + if constexpr (isBigInt) { + object->putDirectOffset(vm, 14, atimeNs); + object->putDirectOffset(vm, 15, mtimeNs); + object->putDirectOffset(vm, 16, ctimeNs); + object->putDirectOffset(vm, 17, birthtimeNs); + } + + return object; +} + +template +inline JSValue constructJSStatsObject(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + Zig::GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); + + auto* structure = getStructure(globalObject); + auto* constructor = getConstructor(globalObject); + JSObject* newTarget = asObject(callFrame->newTarget()); + + if (constructor != newTarget) { + auto scope = DECLARE_THROW_SCOPE(vm); + auto* functionGlobalObject = reinterpret_cast( + // ShadowRealm functions belong to a different global object. + getFunctionRealm(lexicalGlobalObject, newTarget)); + RETURN_IF_EXCEPTION(scope, {}); + structure = InternalFunction::createSubclassStructure( + lexicalGlobalObject, + newTarget, + getStructure(functionGlobalObject)); + } + + JSValue dev = callFrame->argument(0); + JSValue mode = callFrame->argument(1); + JSValue nlink = callFrame->argument(2); + JSValue uid = callFrame->argument(3); + JSValue gid = callFrame->argument(4); + JSValue rdev = callFrame->argument(5); + JSValue blksize = callFrame->argument(6); + JSValue ino = callFrame->argument(7); + JSValue size = callFrame->argument(8); + JSValue blocks = callFrame->argument(9); + JSValue atimeNs = callFrame->argument(10); + JSValue mtimeNs = callFrame->argument(11); + JSValue ctimeNs = callFrame->argument(12); + JSValue birthtimeNs = callFrame->argument(13); + + JSValue atimeMs = atimeNs; + JSValue mtimeMs = mtimeNs; + JSValue ctimeMs = ctimeNs; + JSValue birthtimeMs = birthtimeNs; + + if constexpr (isBigInt) { + // this.atimeMs = atimeNs / kNsPerMsBigInt; + // this.mtimeMs = mtimeNs / kNsPerMsBigInt; + // this.ctimeMs = ctimeNs / kNsPerMsBigInt; + // this.birthtimeMs = birthtimeNs / kNsPerMsBigInt; + const double kNsPerMsBigInt = 1000000; + atimeMs = jsDoubleNumber(atimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + mtimeMs = jsDoubleNumber(mtimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + ctimeMs = jsDoubleNumber(ctimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + birthtimeMs = jsDoubleNumber(birthtimeNs.toBigInt64(globalObject) / kNsPerMsBigInt); + RETURN_IF_EXCEPTION(scope, {}); + } + + JSFinalObject* object = JSC::JSFinalObject::create(vm, structure); + object->putDirect(vm, Identifier::fromString(vm, "dev"_s), dev, 0); + object->putDirect(vm, Identifier::fromString(vm, "mode"_s), mode, 0); + object->putDirect(vm, Identifier::fromString(vm, "nlink"_s), nlink, 0); + object->putDirect(vm, Identifier::fromString(vm, "uid"_s), uid, 0); + object->putDirect(vm, Identifier::fromString(vm, "gid"_s), gid, 0); + object->putDirect(vm, Identifier::fromString(vm, "rdev"_s), rdev, 0); + object->putDirect(vm, Identifier::fromString(vm, "blksize"_s), blksize, 0); + object->putDirect(vm, Identifier::fromString(vm, "ino"_s), ino, 0); + object->putDirect(vm, Identifier::fromString(vm, "size"_s), size, 0); + object->putDirect(vm, Identifier::fromString(vm, "blocks"_s), blocks, 0); + object->putDirect(vm, identifier(vm, DateFieldType::atime), atimeMs, 0); + object->putDirect(vm, identifier(vm, DateFieldType::mtime), mtimeMs, 0); + object->putDirect(vm, identifier(vm, DateFieldType::ctime), ctimeMs, 0); + object->putDirect(vm, identifier(vm, DateFieldType::birthtime), birthtimeMs, 0); + + if constexpr (isBigInt) { + object->putDirect(vm, Identifier::fromString(vm, "atimeNs"_s), atimeNs, 0); + object->putDirect(vm, Identifier::fromString(vm, "mtimeNs"_s), mtimeNs, 0); + object->putDirect(vm, Identifier::fromString(vm, "ctimeNs"_s), ctimeNs, 0); + object->putDirect(vm, Identifier::fromString(vm, "birthtimeNs"_s), birthtimeNs, 0); + } + + return object; +} + +JSC_DEFINE_HOST_FUNCTION(constructStats, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return JSValue::encode(constructJSStatsObject(lexicalGlobalObject, callFrame)); +} + +JSC_DEFINE_HOST_FUNCTION(constructBigIntStats, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return JSValue::encode(constructJSStatsObject(lexicalGlobalObject, callFrame)); +} + +JSC_DEFINE_HOST_FUNCTION(callStats, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return JSValue::encode(callJSStatsFunction(lexicalGlobalObject, callFrame)); +} + +JSC_DEFINE_HOST_FUNCTION(callBigIntStats, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return JSValue::encode(callJSStatsFunction(lexicalGlobalObject, callFrame)); +} + +extern "C" JSC::EncodedJSValue Bun__JSBigIntStatsObjectConstructor(Zig::GlobalObject* globalobject) +{ + return JSValue::encode(globalobject->m_JSStatsBigIntClassStructure.constructor(globalobject)); +} + +extern "C" JSC::EncodedJSValue Bun__JSStatsObjectConstructor(Zig::GlobalObject* globalobject) +{ + return JSValue::encode(globalobject->m_JSStatsClassStructure.constructor(globalobject)); +} + +void initJSStatsClassStructure(JSC::LazyClassStructure::Initializer& init) +{ + auto* prototype = JSStatsPrototype::create(init.vm, init.global, JSStatsPrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); + auto* structure = createJSStatsObjectStructure(init.vm, init.global); + auto* constructor = JSStatsConstructor::create(init.vm, JSStatsConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); + init.setPrototype(prototype); + init.setStructure(structure); + init.setConstructor(constructor); +} + +void initJSBigIntStatsClassStructure(JSC::LazyClassStructure::Initializer& init) +{ + auto* prototype = JSBigIntStatsPrototype::create(init.vm, init.global, JSBigIntStatsPrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); + auto* structure = createJSBigIntStatsObjectStructure(init.vm, init.global); + auto* constructor = JSBigIntStatsConstructor::create(init.vm, JSBigIntStatsConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); + init.setPrototype(prototype); + init.setStructure(structure); + init.setConstructor(constructor); +} + +} // namespace Bun diff --git a/src/bun.js/bindings/NodeFSBinding.h b/src/bun.js/bindings/NodeFSBinding.h new file mode 100644 index 00000000000000..c2d2a60d009230 --- /dev/null +++ b/src/bun.js/bindings/NodeFSBinding.h @@ -0,0 +1,9 @@ + +#include "root.h" + +namespace Bun { + +void initJSStatsClassStructure(JSC::LazyClassStructure::Initializer& init); +void initJSBigIntStatsClassStructure(JSC::LazyClassStructure::Initializer& init); + +} diff --git a/src/bun.js/bindings/NodeFetch.cpp b/src/bun.js/bindings/NodeFetch.cpp index 742a4fb0e7f267..e4395e7ea7b4bb 100644 --- a/src/bun.js/bindings/NodeFetch.cpp +++ b/src/bun.js/bindings/NodeFetch.cpp @@ -21,7 +21,7 @@ using namespace WebCore; // Ensure overriding globals doesn't impact usages. JSC::JSValue createNodeFetchInternalBinding(Zig::GlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* obj = constructEmptyObject(globalObject); obj->putDirectIndex( diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index 943bfd8f7f1ca5..8e1d69e05355c1 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -259,7 +259,7 @@ static EncodedJSValue assignHeadersFromUWebSockets(uWS::HttpRequest* request, JS JSC_DEFINE_HOST_FUNCTION(jsHTTPAssignHeaders, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // This is an internal binding. @@ -326,7 +326,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPAssignHeaders, (JSGlobalObject * globalObject, Ca JSC_DEFINE_HOST_FUNCTION(jsHTTPAssignEventCallback, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // This is an internal binding. @@ -344,7 +344,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPAssignEventCallback, (JSGlobalObject * globalObje JSC_DEFINE_HOST_FUNCTION(jsHTTPSetTimeout, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // This is an internal binding. @@ -361,7 +361,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPSetTimeout, (JSGlobalObject * globalObject, CallF } JSC_DEFINE_HOST_FUNCTION(jsHTTPSetServerIdleTimeout, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); // This is an internal binding. @@ -377,7 +377,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPSetServerIdleTimeout, (JSGlobalObject * globalObj JSC_DEFINE_HOST_FUNCTION(jsHTTPGetHeader, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue headersValue = callFrame->argument(0); @@ -414,7 +414,7 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPGetHeader, (JSGlobalObject * globalObject, CallFr JSC_DEFINE_HOST_FUNCTION(jsHTTPSetHeader, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue headersValue = callFrame->argument(0); diff --git a/src/bun.js/bindings/NodeTimerObject.cpp b/src/bun.js/bindings/NodeTimerObject.cpp index d68786eac1a409..27e1447b6f7d60 100644 --- a/src/bun.js/bindings/NodeTimerObject.cpp +++ b/src/bun.js/bindings/NodeTimerObject.cpp @@ -18,7 +18,7 @@ using namespace JSC; extern "C" void Bun__JSTimeout__call(JSC::EncodedJSValue encodedTimeoutValue, JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(vm.hasPendingTerminationException())) { return; diff --git a/src/bun.js/bindings/NodeURL.cpp b/src/bun.js/bindings/NodeURL.cpp index e3886b5f096084..15f0581e764e12 100644 --- a/src/bun.js/bindings/NodeURL.cpp +++ b/src/bun.js/bindings/NodeURL.cpp @@ -6,7 +6,7 @@ namespace Bun { JSC_DEFINE_HOST_FUNCTION(jsDomainToASCII, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 1) { @@ -74,7 +74,7 @@ JSC_DEFINE_HOST_FUNCTION(jsDomainToASCII, (JSC::JSGlobalObject * globalObject, J JSC_DEFINE_HOST_FUNCTION(jsDomainToUnicode, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 1) { diff --git a/src/bun.js/bindings/NodeVM.cpp b/src/bun.js/bindings/NodeVM.cpp index 4cc8514f24b361..34ec76d3eb2568 100644 --- a/src/bun.js/bindings/NodeVM.cpp +++ b/src/bun.js/bindings/NodeVM.cpp @@ -173,7 +173,7 @@ bool NodeVMGlobalObject::put(JSCell* cell, JSGlobalObject* globalObject, Propert auto* sandbox = thisObject->m_sandbox.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue thisValue = slot.thisValue(); bool isContextualStore = thisValue != JSValue(globalObject); (void)isContextualStore; @@ -217,7 +217,7 @@ bool NodeVMGlobalObject::getOwnPropertySlot(JSObject* cell, JSGlobalObject* glob auto* thisObject = jsCast(cell); if (thisObject->m_sandbox) { auto* contextifiedObject = thisObject->m_sandbox.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); slot.setThisValue(contextifiedObject); if (contextifiedObject->getPropertySlot(globalObject, propertyName, slot)) { @@ -241,7 +241,7 @@ bool NodeVMGlobalObject::defineOwnProperty(JSObject* cell, JSGlobalObject* globa } auto* contextifiedObject = thisObject->m_sandbox.get(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); PropertySlot slot(globalObject, PropertySlot::InternalMethodType::GetOwnProperty, nullptr); @@ -292,7 +292,7 @@ class ScriptOptions { static std::optional fromJS(JSC::JSGlobalObject* globalObject, JSC::JSValue optionsArg, bool& failed) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ScriptOptions opts; JSObject* options; bool any = false; @@ -384,7 +384,7 @@ constructScript(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue newT static JSC::EncodedJSValue runInContext(NodeVMGlobalObject* globalObject, NodeVMScript* script, JSObject* contextifiedObject, JSValue optionsArg) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); // Set the contextified object before evaluating @@ -416,14 +416,14 @@ JSC_DEFINE_CUSTOM_GETTER(scriptGetCachedDataRejected, (JSGlobalObject * globalOb } JSC_DEFINE_HOST_FUNCTION(scriptCreateCachedData, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); return throwVMError(globalObject, scope, "TODO: Script.createCachedData"_s); } JSC_DEFINE_HOST_FUNCTION(scriptRunInContext, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -459,7 +459,7 @@ JSC_DEFINE_HOST_FUNCTION(scriptRunInContext, (JSGlobalObject * globalObject, Cal JSC_DEFINE_HOST_FUNCTION(scriptRunInThisContext, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue thisValue = callFrame->thisValue(); auto* script = jsDynamicCast(thisValue); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -491,7 +491,7 @@ JSC_DEFINE_HOST_FUNCTION(scriptRunInThisContext, (JSGlobalObject * globalObject, JSC_DEFINE_CUSTOM_GETTER(scriptGetSourceMapURL, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValueEncoded, PropertyName)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = JSValue::decode(thisValueEncoded); auto* script = jsDynamicCast(thisValue); @@ -563,7 +563,7 @@ JSC_DEFINE_HOST_FUNCTION(vmModuleRunInNewContext, (JSGlobalObject * globalObject JSC_DEFINE_HOST_FUNCTION(vmModuleRunInThisContext, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto sourceStringValue = callFrame->argument(0); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -599,7 +599,7 @@ JSC_DEFINE_HOST_FUNCTION(vmModuleRunInThisContext, (JSGlobalObject * globalObjec JSC_DEFINE_HOST_FUNCTION(scriptRunInNewContext, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); NodeVMScript* script = jsDynamicCast(callFrame->thisValue()); JSValue contextObjectValue = callFrame->argument(0); // TODO: options @@ -862,7 +862,7 @@ bool NodeVMGlobalObject::deleteProperty(JSCell* cell, JSGlobalObject* globalObje return Base::deleteProperty(cell, globalObject, propertyName, slot); } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* sandbox = thisObject->m_sandbox.get(); diff --git a/src/bun.js/bindings/NodeValidator.cpp b/src/bun.js/bindings/NodeValidator.cpp index dfd177bc3c4672..e1d0092a9ee296 100644 --- a/src/bun.js/bindings/NodeValidator.cpp +++ b/src/bun.js/bindings/NodeValidator.cpp @@ -24,7 +24,7 @@ using namespace JSC; JSC_DEFINE_HOST_FUNCTION(jsFunction_validateInteger, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -72,7 +72,7 @@ JSC::EncodedJSValue V::validateInteger(JSC::ThrowScope& scope, JSC::JSGlobalObje JSC_DEFINE_HOST_FUNCTION(jsFunction_validateNumber, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -128,7 +128,7 @@ JSC::EncodedJSValue V::validateNumber(JSC::ThrowScope& scope, JSC::JSGlobalObjec JSC_DEFINE_HOST_FUNCTION(jsFunction_validateString, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -154,7 +154,7 @@ JSC::EncodedJSValue V::validateString(JSC::ThrowScope& scope, JSC::JSGlobalObjec JSC_DEFINE_HOST_FUNCTION(jsFunction_validateFiniteNumber, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto number = callFrame->argument(0); @@ -181,7 +181,7 @@ JSC::EncodedJSValue V::validateFiniteNumber(JSC::ThrowScope& scope, JSC::JSGloba JSC_DEFINE_HOST_FUNCTION(jsFunction_checkRangesOrGetDefault, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto number = callFrame->argument(0); @@ -212,7 +212,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_checkRangesOrGetDefault, (JSC::JSGlobalObjec JSC_DEFINE_HOST_FUNCTION(jsFunction_validateFunction, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -226,7 +226,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateFunction, (JSC::JSGlobalObject * glo JSC_DEFINE_HOST_FUNCTION(jsFunction_validateBoolean, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -240,7 +240,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateBoolean, (JSC::JSGlobalObject * glob JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePort, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto port = callFrame->argument(0); @@ -306,7 +306,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePort, (JSC::JSGlobalObject * globalO JSC_DEFINE_HOST_FUNCTION(jsFunction_validateAbortSignal, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto signal = callFrame->argument(0); @@ -329,7 +329,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateAbortSignal, (JSC::JSGlobalObject * JSC_DEFINE_HOST_FUNCTION(jsFunction_validateArray, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -339,7 +339,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateArray, (JSC::JSGlobalObject * global } JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, JSValue name, JSValue minLength) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (minLength.isUndefined()) minLength = jsNumber(0); @@ -358,7 +358,7 @@ JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject } JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject* globalObject, JSValue value, ASCIILiteral name, JSValue minLength) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (minLength.isUndefined()) minLength = jsNumber(0); @@ -378,7 +378,7 @@ JSC::EncodedJSValue V::validateArray(JSC::ThrowScope& scope, JSC::JSGlobalObject JSC_DEFINE_HOST_FUNCTION(jsFunction_validateInt32, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -404,7 +404,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateInt32, (JSC::JSGlobalObject * global JSC_DEFINE_HOST_FUNCTION(jsFunction_validateUint32, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -445,7 +445,7 @@ JSC::EncodedJSValue V::validateUint32(JSC::ThrowScope& scope, JSC::JSGlobalObjec JSC_DEFINE_HOST_FUNCTION(jsFunction_validateSignalName, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto signal = callFrame->argument(0); @@ -467,7 +467,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateSignalName, (JSC::JSGlobalObject * g JSC_DEFINE_HOST_FUNCTION(jsFunction_validateEncoding, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto encoding = callFrame->argument(1); @@ -501,7 +501,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateEncoding, (JSC::JSGlobalObject * glo JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePlainFunction, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -515,7 +515,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validatePlainFunction, (JSC::JSGlobalObject JSC_DEFINE_HOST_FUNCTION(jsFunction_validateUndefined, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto value = callFrame->argument(0); @@ -528,7 +528,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunction_validateUndefined, (JSC::JSGlobalObject * gl JSC_DEFINE_HOST_FUNCTION(jsFunction_validateBuffer, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto buffer = callFrame->argument(0); diff --git a/src/bun.js/bindings/Path.cpp b/src/bun.js/bindings/Path.cpp index e0d1e308a136e4..fd05ec5c6a82b7 100644 --- a/src/bun.js/bindings/Path.cpp +++ b/src/bun.js/bindings/Path.cpp @@ -33,7 +33,7 @@ using PathFunction = JSC::EncodedJSValue (*SYSV_ABI)(JSGlobalObject*, bool, Enco template static inline JSC::EncodedJSValue createZigFunction(JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); MarkedArgumentBufferWithSize<8> args = MarkedArgumentBufferWithSize<8>(); for (unsigned i = 0, size = callFrame->argumentCount(); i < size; ++i) { @@ -77,7 +77,7 @@ DEFINE_PATH_FUNCTION(jsFunctionPath_toNamespacedPathWindows, Bun__Path__toNamesp static JSC::JSObject* createPath(JSGlobalObject* globalThis, bool isWindows) { - JSC::VM& vm = globalThis->vm(); + auto& vm = JSC::getVM(globalThis); auto* path = JSC::constructEmptyObject(globalThis); auto builtinNames = WebCore::builtinNames(vm); diff --git a/src/bun.js/bindings/PathInlines.h b/src/bun.js/bindings/PathInlines.h index 363d9269a0d3a2..e0dbf484f4c8cd 100644 --- a/src/bun.js/bindings/PathInlines.h +++ b/src/bun.js/bindings/PathInlines.h @@ -58,11 +58,11 @@ ALWAYS_INLINE bool isAbsolutePath(WTF::String input) extern "C" BunString ResolvePath__joinAbsStringBufCurrentPlatformBunString(JSC::JSGlobalObject*, BunString); /// CWD is determined by the global object's current cwd. -ALWAYS_INLINE WTF::String pathResolveWTFString(JSC::JSGlobalObject* globalToGetCwdFrom, WTF::String input) +ALWAYS_INLINE WTF::String pathResolveWTFString(JSC::JSGlobalObject* globalToGetCwdFrom, const WTF::String& input) { if (isAbsolutePath(input)) return input; BunString in = Bun::toString(input); BunString out = ResolvePath__joinAbsStringBufCurrentPlatformBunString(globalToGetCwdFrom, in); - return out.toWTFString(); + return out.transferToWTFString(); } diff --git a/src/bun.js/bindings/ProcessBindingBuffer.cpp b/src/bun.js/bindings/ProcessBindingBuffer.cpp new file mode 100644 index 00000000000000..c0bb0f079c68e0 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingBuffer.cpp @@ -0,0 +1,159 @@ + +#include "ProcessBindingBuffer.h" +#include +#include "JSBuffer.h" + +namespace Bun { +using namespace JSC; + +#define PROCESS_BINDING_NOT_IMPLEMENTED(str) \ + JSC_DEFINE_HOST_FUNCTION(ProcessBinding_Buffer_##str, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame * callFrame)) \ + { \ + { \ + auto& vm = JSC::getVM(lexicalGlobalObject); \ + auto throwScope = DECLARE_THROW_SCOPE(vm); \ + auto prelude = "process.binding('buffer')."_s; \ + auto name = WTF::ASCIILiteral::fromLiteralUnsafe(#str); \ + auto finale = " is not implemented in Bun. If that breaks something, please file an issue and include a reproducible code sample."_s; \ + auto message = makeString(prelude, name, finale); \ + throwScope.throwException(lexicalGlobalObject, createError(lexicalGlobalObject, message)); \ + return {}; \ + } \ + } + +PROCESS_BINDING_NOT_IMPLEMENTED(asciiSlice) + +PROCESS_BINDING_NOT_IMPLEMENTED(asciiWriteStatic) + +PROCESS_BINDING_NOT_IMPLEMENTED(atob) + +PROCESS_BINDING_NOT_IMPLEMENTED(base64Slice) + +PROCESS_BINDING_NOT_IMPLEMENTED(base64Write) + +PROCESS_BINDING_NOT_IMPLEMENTED(base64urlSlice) + +PROCESS_BINDING_NOT_IMPLEMENTED(base64urlWrite) + +PROCESS_BINDING_NOT_IMPLEMENTED(btoa) + +PROCESS_BINDING_NOT_IMPLEMENTED(byteLengthUtf8) + +PROCESS_BINDING_NOT_IMPLEMENTED(compare) + +PROCESS_BINDING_NOT_IMPLEMENTED(compareOffset) + +PROCESS_BINDING_NOT_IMPLEMENTED(copy) + +PROCESS_BINDING_NOT_IMPLEMENTED(copyArrayBuffer) + +PROCESS_BINDING_NOT_IMPLEMENTED(detachArrayBuffer) + +PROCESS_BINDING_NOT_IMPLEMENTED(fill) + +PROCESS_BINDING_NOT_IMPLEMENTED(getZeroFillToggle) + +PROCESS_BINDING_NOT_IMPLEMENTED(hexSlice) + +PROCESS_BINDING_NOT_IMPLEMENTED(hexWrite) + +PROCESS_BINDING_NOT_IMPLEMENTED(indexOfBuffer) + +PROCESS_BINDING_NOT_IMPLEMENTED(indexOfNumber) + +PROCESS_BINDING_NOT_IMPLEMENTED(indexOfString) + +PROCESS_BINDING_NOT_IMPLEMENTED(isAscii) + +PROCESS_BINDING_NOT_IMPLEMENTED(isUtf8) + +PROCESS_BINDING_NOT_IMPLEMENTED(latin1Slice) + +PROCESS_BINDING_NOT_IMPLEMENTED(latin1WriteStatic) + +PROCESS_BINDING_NOT_IMPLEMENTED(swap16) + +PROCESS_BINDING_NOT_IMPLEMENTED(swap32) + +PROCESS_BINDING_NOT_IMPLEMENTED(swap64) + +PROCESS_BINDING_NOT_IMPLEMENTED(ucs2Slice) + +PROCESS_BINDING_NOT_IMPLEMENTED(ucs2Write) + +PROCESS_BINDING_NOT_IMPLEMENTED(utf8Slice) + +PROCESS_BINDING_NOT_IMPLEMENTED(utf8WriteStatic) + +/* Source for ProcessBindingBuffer.lut.h +@begin processBindingBufferTable + asciiSlice ProcessBinding_Buffer_asciiSlice Function 1 + asciiWriteStatic ProcessBinding_Buffer_asciiWriteStatic Function 1 + atob ProcessBinding_Buffer_atob Function 1 + base64Slice ProcessBinding_Buffer_base64Slice Function 1 + base64Write ProcessBinding_Buffer_base64Write Function 1 + base64urlSlice ProcessBinding_Buffer_base64urlSlice Function 1 + base64urlWrite ProcessBinding_Buffer_base64urlWrite Function 1 + btoa ProcessBinding_Buffer_btoa Function 1 + byteLengthUtf8 ProcessBinding_Buffer_byteLengthUtf8 Function 1 + compare ProcessBinding_Buffer_compare Function 1 + compareOffset ProcessBinding_Buffer_compareOffset Function 1 + copy ProcessBinding_Buffer_copy Function 1 + copyArrayBuffer ProcessBinding_Buffer_copyArrayBuffer Function 1 + detachArrayBuffer ProcessBinding_Buffer_detachArrayBuffer Function 1 + fill ProcessBinding_Buffer_fill Function 1 + getZeroFillToggle ProcessBinding_Buffer_getZeroFillToggle Function 1 + hexSlice ProcessBinding_Buffer_hexSlice Function 1 + hexWrite ProcessBinding_Buffer_hexWrite Function 1 + indexOfBuffer ProcessBinding_Buffer_indexOfBuffer Function 1 + indexOfNumber ProcessBinding_Buffer_indexOfNumber Function 1 + indexOfString ProcessBinding_Buffer_indexOfString Function 1 + isAscii ProcessBinding_Buffer_isAscii Function 1 + isUtf8 ProcessBinding_Buffer_isUtf8 Function 1 + latin1Slice ProcessBinding_Buffer_latin1Slice Function 1 + latin1WriteStatic ProcessBinding_Buffer_latin1WriteStatic Function 1 + swap16 ProcessBinding_Buffer_swap16 Function 1 + swap32 ProcessBinding_Buffer_swap32 Function 1 + swap64 ProcessBinding_Buffer_swap64 Function 1 + ucs2Slice ProcessBinding_Buffer_ucs2Slice Function 1 + ucs2Write ProcessBinding_Buffer_ucs2Write Function 1 + utf8Slice ProcessBinding_Buffer_utf8Slice Function 1 + utf8WriteStatic ProcessBinding_Buffer_utf8WriteStatic Function 1 +@end +*/ +#include "ProcessBindingBuffer.lut.h" + +const ClassInfo ProcessBindingBuffer::s_info = { "ProcessBindingBuffer"_s, &Base::s_info, &processBindingBufferTable, nullptr, CREATE_METHOD_TABLE(ProcessBindingBuffer) }; + +ProcessBindingBuffer* ProcessBindingBuffer::create(VM& vm, Structure* structure) +{ + ProcessBindingBuffer* obj = new (NotNull, allocateCell(vm)) ProcessBindingBuffer(vm, structure); + obj->finishCreation(vm); + return obj; +} + +Structure* ProcessBindingBuffer::createStructure(VM& vm, JSGlobalObject* globalObject) +{ + return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), ProcessBindingBuffer::info()); +} + +void ProcessBindingBuffer::finishCreation(JSC::VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + + putDirect(vm, Identifier::fromString(vm, "kMaxLength"_s), jsNumber(Bun::Buffer::kMaxLength), 0); + putDirect(vm, Identifier::fromString(vm, "kStringMaxLength"_s), jsNumber(Bun::Buffer::kStringMaxLength), 0); +} + +template +void ProcessBindingBuffer::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + ProcessBindingBuffer* thisObject = jsCast(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); +} + +DEFINE_VISIT_CHILDREN(ProcessBindingBuffer); + +} // namespace Bun diff --git a/src/bun.js/bindings/ProcessBindingBuffer.h b/src/bun.js/bindings/ProcessBindingBuffer.h new file mode 100644 index 00000000000000..62add4ca3ec4f0 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingBuffer.h @@ -0,0 +1,37 @@ +#pragma once +#include "root.h" + +namespace Bun { + +using namespace JSC; + +// The object returned from process.binding('buffer') +class ProcessBindingBuffer final : public JSC::JSNonFinalObject { +public: + DECLARE_INFO; + DECLARE_VISIT_CHILDREN; + + using Base = JSC::JSNonFinalObject; + + static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable; + + static ProcessBindingBuffer* create(JSC::VM& vm, JSC::Structure* structure); + static Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject); + + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ProcessBindingBuffer, Base); + return &vm.plainObjectSpace(); + } + +private: + void finishCreation(JSC::VM& vm); + + ProcessBindingBuffer(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } +}; + +} // namespace Bun diff --git a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp index c86eec8658c43c..17a2fb6abbc35c 100644 --- a/src/bun.js/bindings/ProcessBindingTTYWrap.cpp +++ b/src/bun.js/bindings/ProcessBindingTTYWrap.cpp @@ -201,7 +201,7 @@ JSC_DEFINE_HOST_FUNCTION(jsTTYSetMode, (JSC::JSGlobalObject * globalObject, Call return JSValue::encode(jsNumber(Source__setRawModeStdin(raw))); #else - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() != 2) { @@ -229,7 +229,7 @@ JSC_DEFINE_HOST_FUNCTION(jsTTYSetMode, (JSC::JSGlobalObject * globalObject, Call JSC_DEFINE_HOST_FUNCTION(TTYWrap_functionSetMode, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto argCount = callFrame->argumentCount(); auto throwScope = DECLARE_THROW_SCOPE(vm); if (argCount == 0) { @@ -266,7 +266,7 @@ JSC_DEFINE_HOST_FUNCTION(TTYWrap_functionSetMode, JSC_DEFINE_HOST_FUNCTION(TTYWrap_functionGetWindowSize, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto argCount = callFrame->argumentCount(); auto throwScope = DECLARE_THROW_SCOPE(vm); if (argCount == 0) { @@ -301,7 +301,7 @@ JSC_DEFINE_HOST_FUNCTION(TTYWrap_functionGetWindowSize, JSC_DEFINE_HOST_FUNCTION(Process_functionInternalGetWindowSize, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto argCount = callFrame->argumentCount(); auto throwScope = DECLARE_THROW_SCOPE(vm); if (argCount == 0) { @@ -403,7 +403,7 @@ class TTYWrapConstructor final : public JSC::InternalFunction { static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); throwTypeError(globalObject, scope, "TTYWrapConstructor cannot be called as a function"_s); @@ -413,7 +413,7 @@ class TTYWrapConstructor final : public JSC::InternalFunction { // new TTY() static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* constructor = jsDynamicCast(callframe->jsCallee()); @@ -491,7 +491,7 @@ const ClassInfo TTYWrapConstructor::s_info = { "TTY"_s, &Base::s_info, nullptr, JSValue createBunTTYFunctions(Zig::GlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* obj = constructEmptyObject(globalObject); obj->putDirect(vm, PropertyName(Identifier::fromString(vm, "isatty"_s)), JSFunction::create(vm, globalObject, 0, "isatty"_s, Zig::jsFunctionTty_isatty, ImplementationVisibility::Public), 0); @@ -505,7 +505,7 @@ JSValue createBunTTYFunctions(Zig::GlobalObject* globalObject) JSValue createNodeTTYWrapObject(JSC::JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* obj = constructEmptyObject(globalObject); obj->putDirect(vm, PropertyName(Identifier::fromString(vm, "isTTY"_s)), JSFunction::create(vm, globalObject, 0, "isatty"_s, Zig::jsFunctionTty_isatty, ImplementationVisibility::Public), 0); diff --git a/src/bun.js/bindings/ProcessBindingUV.cpp b/src/bun.js/bindings/ProcessBindingUV.cpp index e29cd4d3975312..2738b9b0fed6a3 100644 --- a/src/bun.js/bindings/ProcessBindingUV.cpp +++ b/src/bun.js/bindings/ProcessBindingUV.cpp @@ -356,7 +356,7 @@ namespace ProcessBindingUV { JSC_DEFINE_HOST_FUNCTION(jsErrname, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto arg0 = callFrame->argument(0); // Node.js crashes here: @@ -378,7 +378,7 @@ JSC_DEFINE_HOST_FUNCTION(jsErrname, (JSGlobalObject * globalObject, JSC::CallFra JSC_DEFINE_HOST_FUNCTION(jsGetErrorMap, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto map = JSC::JSMap::create(vm, globalObject->mapStructure()); // Inlining each of these via macros costs like 300 KB. diff --git a/src/bun.js/bindings/S3Error.cpp b/src/bun.js/bindings/S3Error.cpp index a3ae91651c64b8..0ce4d9d093a9c8 100644 --- a/src/bun.js/bindings/S3Error.cpp +++ b/src/bun.js/bindings/S3Error.cpp @@ -25,7 +25,7 @@ SYSV_ABI JSC::EncodedJSValue S3Error__toErrorInstance(const S3Error* arg0, { S3Error err = *arg0; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue message = JSC::jsUndefined(); @@ -40,7 +40,7 @@ SYSV_ABI JSC::EncodedJSValue S3Error__toErrorInstance(const S3Error* arg0, JSC::JSObject* result = JSC::ErrorInstance::create(globalObject, prototype, message, options); result->putDirect( vm, vm.propertyNames->name, - JSC::JSValue(defaultGlobalObject(globalObject)->commonStrings().S3ErrorString(globalObject)), + JSC::JSValue(defaultGlobalObject(globalObject)->commonStrings().s3ErrorString(globalObject)), JSC::PropertyAttribute::DontEnum | 0); if (err.code.tag != BunStringTag::Empty) { JSC::JSValue code = Bun::toJS(globalObject, err.code); diff --git a/src/bun.js/bindings/SQLClient.cpp b/src/bun.js/bindings/SQLClient.cpp index af6737872cf548..3c04d2e7267143 100644 --- a/src/bun.js/bindings/SQLClient.cpp +++ b/src/bun.js/bindings/SQLClient.cpp @@ -282,7 +282,7 @@ static JSC::JSValue toJS(JSC::VM& vm, JSC::JSGlobalObject* globalObject, DataCel static JSC::JSValue toJS(JSC::Structure* structure, DataCell* cells, unsigned count, JSC::JSGlobalObject* globalObject, Bun::BunStructureFlags flags, BunResultMode result_mode) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); switch (result_mode) { @@ -420,7 +420,7 @@ typedef struct ExternColumnIdentifier { extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject, JSC::JSCell* owner, unsigned int inlineCapacity, ExternColumnIdentifier* namesPtr) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); std::span names(namesPtr, inlineCapacity); @@ -457,7 +457,7 @@ extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject extern "C" EncodedJSValue JSC__createEmptyObjectWithStructure(JSC::JSGlobalObject* globalObject, JSC::Structure* structure) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* object = JSC::constructEmptyObject(vm, structure); ensureStillAliveHere(object); diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h index 6122948614cdbb..51b49cada1f2cf 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.h +++ b/src/bun.js/bindings/ScriptExecutionContext.h @@ -2,7 +2,6 @@ #include "root.h" #include "ActiveDOMObject.h" -#include "ContextDestructionObserver.h" #include #include #include @@ -33,6 +32,8 @@ class MessagePort; class ScriptExecutionContext; class EventLoopTask; +class ContextDestructionObserver; + using ScriptExecutionContextIdentifier = uint32_t; DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ScriptExecutionContext); diff --git a/src/bun.js/bindings/Serialization.cpp b/src/bun.js/bindings/Serialization.cpp index 93a1393d660d7f..f48b8bf35cab60 100644 --- a/src/bun.js/bindings/Serialization.cpp +++ b/src/bun.js/bindings/Serialization.cpp @@ -25,7 +25,7 @@ extern "C" SerializedValueSlice Bun__serializeJSValue(JSGlobalObject* globalObje ExceptionOr> serialized = SerializedScriptValue::create(*globalObject, value, WTFMove(transferList), dummyPorts); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (serialized.hasException()) { diff --git a/src/bun.js/bindings/Undici.cpp b/src/bun.js/bindings/Undici.cpp index c3649d7a341ee5..95c3fdbef2f445 100644 --- a/src/bun.js/bindings/Undici.cpp +++ b/src/bun.js/bindings/Undici.cpp @@ -29,7 +29,7 @@ using namespace WebCore; // Ensure overriding globals doesn't impact usages. JSC::JSValue createUndiciInternalBinding(Zig::GlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* obj = constructEmptyObject(globalObject, globalObject->objectPrototype(), 11); obj->putDirectIndex( diff --git a/src/bun.js/bindings/UtilInspect.cpp b/src/bun.js/bindings/UtilInspect.cpp index 5e72a31557d173..56724f8057a3dc 100644 --- a/src/bun.js/bindings/UtilInspect.cpp +++ b/src/bun.js/bindings/UtilInspect.cpp @@ -46,7 +46,7 @@ extern "C" JSC::EncodedJSValue JSC__JSValue__callCustomInspectFunction( { JSValue functionToCall = JSValue::decode(encodedFunctionValue); JSValue thisValue = JSValue::decode(encodedThisValue); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSObject* options = Bun::createInspectOptionsObject(vm, globalObject, max_depth, colors); diff --git a/src/bun.js/bindings/ZigGeneratedCode.cpp b/src/bun.js/bindings/ZigGeneratedCode.cpp index 45d939c024cb7b..d420e3824c3062 100644 --- a/src/bun.js/bindings/ZigGeneratedCode.cpp +++ b/src/bun.js/bindings/ZigGeneratedCode.cpp @@ -20,7 +20,7 @@ using namespace WebCore; // JSC_DEFINE_JIT_OPERATION(FFI__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, JSC::JSUint8Array* arg1)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -67,7 +67,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u8__fastpathWr // JSC_DEFINE_JIT_OPERATION(Reader__u8__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -116,7 +116,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u16__fastpathW // JSC_DEFINE_JIT_OPERATION(Reader__u16__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -162,7 +162,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__u32__fastpathW // JSC_DEFINE_JIT_OPERATION(Reader__u32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -208,7 +208,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__ptr__fastpathW // JSC_DEFINE_JIT_OPERATION(Reader__ptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -254,7 +254,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i8__fastpathWr // JSC_DEFINE_JIT_OPERATION(Reader__i8__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -300,7 +300,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i16__fastpathW // JSC_DEFINE_JIT_OPERATION(Reader__i16__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -346,7 +346,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i32__fastpathW // JSC_DEFINE_JIT_OPERATION(Reader__i32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -392,7 +392,7 @@ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(Reader__i64__fastpathW // JSC_DEFINE_JIT_OPERATION(Reader__i64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -438,7 +438,7 @@ BUN_DECLARE_HOST_FUNCTION(Reader__u64__slowpathWrapper); // JSC_DEFINE_JIT_OPERATION(Reader__u64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -484,7 +484,7 @@ BUN_DECLARE_HOST_FUNCTION(Reader__intptr__slowpathWrapper); // JSC_DEFINE_JIT_OPERATION(Reader__intptr__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -530,7 +530,7 @@ BUN_DECLARE_HOST_FUNCTION(Reader__f32__slowpathWrapper); // JSC_DEFINE_JIT_OPERATION(Reader__f32__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -576,7 +576,7 @@ BUN_DECLARE_HOST_FUNCTION(Reader__f64__slowpathWrapper); // JSC_DEFINE_JIT_OPERATION(Reader__f64__fastpathWrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, int64_t arg1, int32_t arg2)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index da9ba3652a7f40..c0d2156bed36c7 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -161,10 +161,16 @@ #include "JSX509Certificate.h" #include "JSS3File.h" #include "S3Error.h" +#include "ProcessBindingBuffer.h" +#include + #if ENABLE(REMOTE_INSPECTOR) #include "JavaScriptCore/RemoteInspectorServer.h" #endif +#include "NodeFSBinding.h" +#include "NodeDirent.h" + #if !OS(WINDOWS) #include #endif @@ -233,6 +239,22 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c return; has_loaded_jsc = true; JSC::Config::enableRestrictedOptions(); +#if OS(LINUX) + { + // By default, JavaScriptCore's garbage collector sends SIGUSR1 to the JS thread to suspend + // and resume it in order to scan its stack memory. Whatever signal it uses can't be + // reliably intercepted by JS code, and several npm packages use SIGUSR1 for various + // features. We tell it to use SIGPWR instead, which we assume is unlikely to be reliable + // for its stated purpose. Mono's garbage collector also uses SIGPWR: + // https://www.mono-project.com/docs/advanced/embedding/#signal-handling + // + // This call needs to be before most of the other JSC initialization, as we can't + // reconfigure which signal is used once the signal handler has already been registered. + bool configure_signal_success = JSConfigureSignalForGC(SIGPWR); + ASSERT(configure_signal_success); + ASSERT(g_wtfConfig.sigThreadSuspendResume == SIGPWR); + } +#endif std::set_terminate([]() { Zig__GlobalObject__onCrash(); }); WTF::initializeMainThread(); @@ -847,7 +869,7 @@ JSC::Structure* GlobalObject::createStructure(JSC::VM& vm) void Zig::GlobalObject::resetOnEachMicrotaskTick() { - JSC::VM& vm = this->vm(); + auto& vm = this->vm(); if (this->asyncHooksNeedsCleanup) { vm.setOnEachMicrotaskTick(&cleanupAsyncHooksData); } else { @@ -875,6 +897,8 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(void* console_client, vm.heap.acquireAccess(); JSC::JSLockHolder locker(vm); + vm.heap.disableStopIfNecessaryTimer(); + WebCore::JSVMClientData::create(&vm, Bun__getVM()); const auto createGlobalObject = [&]() -> Zig::GlobalObject* { @@ -976,7 +1000,7 @@ JSC_DEFINE_HOST_FUNCTION(functionFulfillModuleSync, { Zig::GlobalObject* globalObject = jsCast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue key = callFrame->argument(0); @@ -1031,7 +1055,7 @@ extern "C" bool Zig__GlobalObject__resetModuleRegistryMap(JSC__JSGlobalObject* g if (map_ptr == nullptr) return false; JSC::JSMap* map = reinterpret_cast(map_ptr); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (JSC::JSObject* obj = JSC::jsDynamicCast(globalObject->moduleLoader())) { auto identifier = JSC::Identifier::fromString(globalObject->vm(), "registry"_s); @@ -1100,7 +1124,7 @@ using namespace WebCore; static JSGlobalObject* deriveShadowRealmGlobalObject(JSGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); Zig::GlobalObject* shadow = Zig::GlobalObject::create(vm, Zig::GlobalObject::createStructure(vm)); shadow->setConsole(shadow); @@ -1418,7 +1442,7 @@ JSC_DEFINE_HOST_FUNCTION(functionGetSelf, JSC_DEFINE_HOST_FUNCTION(functionSetSelf, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue value = callFrame->argument(0); // Chrome DevTools: // > Object.getOwnPropertyDescriptor(globalThis, "self") @@ -1434,7 +1458,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSetSelf, JSC_DEFINE_HOST_FUNCTION(functionQueueMicrotask, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() == 0) { JSC::throwTypeError(globalObject, scope, "queueMicrotask requires 1 argument (a function)"_s); @@ -1476,7 +1500,7 @@ JSC_DEFINE_HOST_FUNCTION(functionNativeMicrotaskTrampoline, JSC_DEFINE_HOST_FUNCTION(functionSetTimeout, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue job = callFrame->argument(0); JSC::JSValue num = callFrame->argument(1); JSC::JSValue arguments = {}; @@ -1531,7 +1555,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSetTimeout, JSC_DEFINE_HOST_FUNCTION(functionSetInterval, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue job = callFrame->argument(0); JSC::JSValue num = callFrame->argument(1); JSC::JSValue arguments = {}; @@ -1590,7 +1614,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSetInterval, JSC_DEFINE_HOST_FUNCTION(functionClearInterval, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (callFrame->argumentCount() == 0) { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); @@ -1617,7 +1641,7 @@ JSC_DEFINE_HOST_FUNCTION(functionClearInterval, JSC_DEFINE_HOST_FUNCTION(functionClearTimeout, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (callFrame->argumentCount() == 0) { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); @@ -1644,7 +1668,7 @@ JSC_DEFINE_HOST_FUNCTION(functionClearTimeout, JSC_DEFINE_HOST_FUNCTION(functionStructuredClone, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() == 0) { @@ -1689,7 +1713,7 @@ JSC_DEFINE_HOST_FUNCTION(functionStructuredClone, JSC_DEFINE_HOST_FUNCTION(functionBTOA, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); if (callFrame->argumentCount() == 0) { @@ -1739,7 +1763,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBTOA, JSC_DEFINE_HOST_FUNCTION(functionATOB, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); if (callFrame->argumentCount() == 0) { @@ -2005,7 +2029,7 @@ JSC_DEFINE_HOST_FUNCTION(makeDOMExceptionForBuiltins, (JSGlobalObject * globalOb ASSERT(callFrame); ASSERT(callFrame->argumentCount() == 2); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); DeferTermination deferScope(vm); auto scope = DECLARE_CATCH_SCOPE(vm); @@ -2052,7 +2076,7 @@ JSC_DEFINE_HOST_FUNCTION(addAbortAlgorithmToSignal, (JSGlobalObject * globalObje ASSERT(callFrame); ASSERT(callFrame->argumentCount() == 2); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* abortSignal = jsDynamicCast(callFrame->uncheckedArgument(0)); if (UNLIKELY(!abortSignal)) return JSValue::encode(JSValue(JSC::JSValue::JSFalse)); @@ -2179,7 +2203,7 @@ extern "C" int32_t ReadableStreamTag__tagged(Zig::GlobalObject* globalObject, JS return -1; } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (!object->inherits()) { auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -2261,7 +2285,7 @@ extern "C" int32_t ReadableStreamTag__tagged(Zig::GlobalObject* globalObject, JS extern "C" JSC__JSValue ZigGlobalObject__createNativeReadableStream(Zig::GlobalObject* globalObject, JSC__JSValue nativePtr) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto& builtinNames = WebCore::builtinNames(vm); @@ -2287,7 +2311,7 @@ extern "C" JSC__JSValue Bun__Jest__testModuleObject(Zig::GlobalObject* globalObj static inline JSC__JSValue ZigGlobalObject__readableStreamToArrayBufferBody(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -2333,7 +2357,7 @@ extern "C" JSC__JSValue ZigGlobalObject__readableStreamToArrayBuffer(Zig::Global extern "C" JSC__JSValue ZigGlobalObject__readableStreamToBytes(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue); extern "C" JSC__JSValue ZigGlobalObject__readableStreamToBytes(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -2373,7 +2397,7 @@ extern "C" JSC__JSValue ZigGlobalObject__readableStreamToBytes(Zig::GlobalObject extern "C" JSC__JSValue ZigGlobalObject__readableStreamToText(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue); extern "C" JSC__JSValue ZigGlobalObject__readableStreamToText(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSFunction* function = nullptr; if (auto readableStreamToText = globalObject->m_readableStreamToText.get()) { @@ -2393,7 +2417,7 @@ extern "C" JSC__JSValue ZigGlobalObject__readableStreamToText(Zig::GlobalObject* extern "C" JSC__JSValue ZigGlobalObject__readableStreamToFormData(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue, JSC__JSValue contentTypeValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSFunction* function = nullptr; if (auto readableStreamToFormData = globalObject->m_readableStreamToFormData.get()) { @@ -2415,7 +2439,7 @@ extern "C" JSC__JSValue ZigGlobalObject__readableStreamToFormData(Zig::GlobalObj extern "C" JSC__JSValue ZigGlobalObject__readableStreamToJSON(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue); extern "C" JSC__JSValue ZigGlobalObject__readableStreamToJSON(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSFunction* function = nullptr; if (auto readableStreamToJSON = globalObject->m_readableStreamToJSON.get()) { @@ -2436,7 +2460,7 @@ extern "C" JSC__JSValue ZigGlobalObject__readableStreamToJSON(Zig::GlobalObject* extern "C" JSC__JSValue ZigGlobalObject__readableStreamToBlob(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue); extern "C" JSC__JSValue ZigGlobalObject__readableStreamToBlob(Zig::GlobalObject* globalObject, JSC__JSValue readableStreamValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSFunction* function = nullptr; if (auto readableStreamToBlob = globalObject->m_readableStreamToBlob.get()) { @@ -2457,7 +2481,7 @@ extern "C" JSC__JSValue ZigGlobalObject__readableStreamToBlob(Zig::GlobalObject* JSC_DECLARE_HOST_FUNCTION(functionReadableStreamToArrayBuffer); JSC_DEFINE_HOST_FUNCTION(functionReadableStreamToArrayBuffer, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (UNLIKELY(callFrame->argumentCount() < 1)) { auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -2472,7 +2496,7 @@ JSC_DEFINE_HOST_FUNCTION(functionReadableStreamToArrayBuffer, (JSGlobalObject * JSC_DECLARE_HOST_FUNCTION(functionReadableStreamToBytes); JSC_DEFINE_HOST_FUNCTION(functionReadableStreamToBytes, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (UNLIKELY(callFrame->argumentCount() < 1)) { auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -2486,7 +2510,7 @@ JSC_DEFINE_HOST_FUNCTION(functionReadableStreamToBytes, (JSGlobalObject * global JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotask, (JSGlobalObject * globalObject, CallFrame* callframe)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); auto job = callframe->argument(0); @@ -2543,7 +2567,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotask, (JSGlobalObject * globalObj JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotaskVariadic, (JSGlobalObject * globalObject, CallFrame* callframe)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); auto job = callframe->argument(0); @@ -2620,7 +2644,7 @@ void GlobalObject::createCallSitesFromFrames(Zig::GlobalObject* globalObject, JS JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncAppendStackTrace, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::ErrorInstance* source = jsDynamicCast(callFrame->argument(0)); @@ -2645,7 +2669,7 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncAppendStackTrace, (JSC::JSGlobalObj JSC_DEFINE_HOST_FUNCTION(jsFunctionDefaultErrorPrepareStackTrace, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* globalObject = defaultGlobalObject(lexicalGlobalObject); @@ -2665,7 +2689,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionDefaultErrorPrepareStackTrace, (JSGlobalObjec JSC_DEFINE_CUSTOM_GETTER(errorInstanceLazyStackCustomGetter, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* errorObject = jsDynamicCast(JSValue::decode(thisValue)); @@ -2692,7 +2716,7 @@ JSC_DEFINE_CUSTOM_GETTER(errorInstanceLazyStackCustomGetter, (JSGlobalObject * g JSC_DEFINE_CUSTOM_SETTER(errorInstanceLazyStackCustomSetter, (JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, PropertyName)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue decodedValue = JSValue::decode(thisValue); if (auto* object = decodedValue.getObject()) { object->putDirect(vm, vm.propertyNames->stack, JSValue::decode(value), 0); @@ -2704,7 +2728,7 @@ JSC_DEFINE_CUSTOM_SETTER(errorInstanceLazyStackCustomSetter, (JSGlobalObject * g JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue objectArg = callFrame->argument(0); @@ -2761,7 +2785,7 @@ JSC_DEFINE_CUSTOM_GETTER(moduleNamespacePrototypeGetESModuleMarker, (JSGlobalObj JSC_DEFINE_CUSTOM_SETTER(moduleNamespacePrototypeSetESModuleMarker, (JSGlobalObject * globalObject, JSC::EncodedJSValue encodedThisValue, JSC::EncodedJSValue encodedValue, PropertyName)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue thisValue = JSValue::decode(encodedThisValue); JSModuleNamespaceObject* moduleNamespaceObject = jsDynamicCast(thisValue); if (!moduleNamespaceObject) { @@ -2783,6 +2807,12 @@ void GlobalObject::finishCreation(VM& vm) m_http2_commongStrings.initialize(); Bun::addNodeModuleConstructorProperties(vm, this); + + m_JSDirentClassStructure.initLater( + [](LazyClassStructure::Initializer& init) { + Bun::initJSDirentClassStructure(init); + }); + m_JSX509CertificateClassStructure.initLater([](LazyClassStructure::Initializer& init) { setupX509CertificateClassStructure(init); }); @@ -2873,6 +2903,16 @@ void GlobalObject::finishCreation(VM& vm) jsDynamicCast(init.owner))); }); + m_JSStatsClassStructure.initLater( + [](LazyClassStructure::Initializer& init) { + Bun::initJSStatsClassStructure(init); + }); + + m_JSStatsBigIntClassStructure.initLater( + [](LazyClassStructure::Initializer& init) { + Bun::initJSBigIntStatsClassStructure(init); + }); + m_memoryFootprintStructure.initLater( [](const JSC::LazyProperty::Initializer& init) { init.set( @@ -3186,6 +3226,14 @@ void GlobalObject::finishCreation(VM& vm) InternalModuleRegistry::createStructure(init.vm, init.owner))); }); + m_processBindingBuffer.initLater( + [](const JSC::LazyProperty::Initializer& init) { + init.set( + ProcessBindingBuffer::create( + init.vm, + ProcessBindingBuffer::createStructure(init.vm, init.owner))); + }); + m_processBindingConstants.initLater( [](const JSC::LazyProperty::Initializer& init) { init.set( @@ -3345,7 +3393,7 @@ JSC_DEFINE_CUSTOM_SETTER(JSDOMFileConstructor_setter, return false; } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); globalObject->putDirect(vm, property, JSValue::decode(value), 0); return true; } @@ -3355,7 +3403,7 @@ extern "C" JSC__JSValue Bun__Timer__setImmediate(JSC__JSGlobalObject* arg0, JSC_ JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto argCount = callFrame->argumentCount(); @@ -3400,7 +3448,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, // `console.Console` or `import { Console } from 'console';` JSC_DEFINE_CUSTOM_GETTER(getConsoleConstructor, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto console = JSValue::decode(thisValue).getObject(); JSC::JSFunction* createConsoleConstructor = JSC::JSFunction::create(vm, globalObject, consoleObjectCreateConsoleConstructorCodeGenerator(vm), globalObject); JSC::MarkedArgumentBuffer args; @@ -3419,7 +3467,7 @@ JSC_DEFINE_CUSTOM_GETTER(getConsoleConstructor, (JSGlobalObject * globalObject, // `console._stdout` is equal to `process.stdout` JSC_DEFINE_CUSTOM_GETTER(getConsoleStdout, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto console = JSValue::decode(thisValue).getObject(); auto global = jsCast(globalObject); @@ -3435,7 +3483,7 @@ JSC_DEFINE_CUSTOM_GETTER(getConsoleStdout, (JSGlobalObject * globalObject, Encod // `console._stderr` is equal to `process.stderr` JSC_DEFINE_CUSTOM_GETTER(getConsoleStderr, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto console = JSValue::decode(thisValue).getObject(); auto global = jsCast(globalObject); @@ -3456,7 +3504,7 @@ JSC_DEFINE_CUSTOM_SETTER(EventSource_setter, return false; } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); globalObject->putDirect(vm, property, JSValue::decode(value), 0); return true; } @@ -3464,7 +3512,7 @@ JSC_DEFINE_CUSTOM_SETTER(EventSource_setter, JSC_DEFINE_HOST_FUNCTION(jsFunctionToClass, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { // Mimick the behavior of class Foo {} for a regular JSFunction. - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto target = callFrame->argument(0).toObject(globalObject); auto name = callFrame->argument(1); @@ -3499,7 +3547,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionToClass, (JSC::JSGlobalObject * globalObject, EncodedJSValue GlobalObject::assignToStream(JSValue stream, JSValue controller) { - JSC::VM& vm = this->vm(); + auto& vm = this->vm(); JSC::JSFunction* function = this->m_assignToStream.get(); if (!function) { function = JSFunction::create(vm, this, static_cast(readableStreamInternalsAssignToStreamCodeGenerator(vm)), this); @@ -3701,7 +3749,7 @@ JSC_DEFINE_HOST_FUNCTION(functionJsGc, extern "C" void JSC__JSGlobalObject__addGc(JSC__JSGlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); globalObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "gc"_s), 0, functionJsGc, ImplementationVisibility::Public, JSC::NoIntrinsic, PropertyAttribute::DontEnum | 0); } @@ -3826,6 +3874,9 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_lazyRequireCacheObject.visit(visitor); thisObject->m_lazyTestModuleObject.visit(visitor); thisObject->m_memoryFootprintStructure.visit(visitor); + thisObject->m_JSStatsClassStructure.visit(visitor); + thisObject->m_JSStatsBigIntClassStructure.visit(visitor); + thisObject->m_JSDirentClassStructure.visit(visitor); thisObject->m_NapiClassStructure.visit(visitor); thisObject->m_NapiExternalStructure.visit(visitor); thisObject->m_NAPIFunctionStructure.visit(visitor); @@ -3875,7 +3926,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) extern "C" bool JSGlobalObject__setTimeZone(JSC::JSGlobalObject* globalObject, const ZigString* timeZone) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (WTF::setTimeZoneOverride(Zig::toString(*timeZone))) { vm.dateCache.resetIfNecessarySlow(); @@ -4098,7 +4149,7 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* j const SourceOrigin& sourceOrigin) { auto* globalObject = reinterpret_cast(jsGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (globalObject->onLoadPlugins.hasVirtualModules()) { @@ -4189,7 +4240,7 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* j static JSC::JSInternalPromise* rejectedInternalPromise(JSC::JSGlobalObject* globalObject, JSC::JSValue value) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, value); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt() | JSC::JSPromise::isFirstResolvingFunctionCalledFlag | static_cast(JSC::JSPromise::Status::Rejected))); @@ -4200,7 +4251,7 @@ JSC::JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalOb JSModuleLoader* loader, JSValue key, JSValue parameters, JSValue script) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 6317eca83d0a81..b34cb5aec5150c 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -248,6 +248,7 @@ class GlobalObject : public Bun::GlobalScope { JSObject* requireResolveFunctionUnbound() const { return m_requireResolveFunctionUnbound.getInitializedOnMainThread(this); } Bun::InternalModuleRegistry* internalModuleRegistry() const { return m_internalModuleRegistry.getInitializedOnMainThread(this); } + JSObject* processBindingBuffer() const { return m_processBindingBuffer.getInitializedOnMainThread(this); } JSObject* processBindingConstants() const { return m_processBindingConstants.getInitializedOnMainThread(this); } JSObject* lazyRequireCacheObject() const { return m_lazyRequireCacheObject.getInitializedOnMainThread(this); } @@ -483,6 +484,9 @@ class GlobalObject : public Bun::GlobalScope { LazyProperty m_JSS3FileStructure; LazyProperty m_S3ErrorStructure; + JSC::LazyClassStructure m_JSStatsClassStructure; + JSC::LazyClassStructure m_JSStatsBigIntClassStructure; + JSC::LazyClassStructure m_JSDirentClassStructure; JSObject* cryptoObject() const { return m_cryptoObject.getInitializedOnMainThread(this); } JSObject* JSDOMFileConstructor() const { return m_JSDOMFileConstructor.getInitializedOnMainThread(this); } @@ -576,6 +580,7 @@ class GlobalObject : public Bun::GlobalScope { LazyProperty m_requireFunctionUnbound; LazyProperty m_requireResolveFunctionUnbound; LazyProperty m_internalModuleRegistry; + LazyProperty m_processBindingBuffer; LazyProperty m_processBindingConstants; LazyProperty m_importMetaObjectStructure; LazyProperty m_asyncBoundFunctionStructure; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 4a8338f6acc0e1..f123454b52193c 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -259,7 +259,7 @@ extern "C" int8_t AsymmetricMatcherConstructorType__fromJS(JSC__JSGlobalObject* JSValue value = JSValue::decode(encodedValue); if (value.isObject()) { JSObject* object = value.getObject(); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (globalObject->numberObjectConstructor() == object) { return static_cast(AsymmetricMatcherConstructorType::Number); @@ -663,6 +663,9 @@ JSValue getIndexWithoutAccessors(JSGlobalObject* globalObject, JSObject* obj, ui return JSValue(); } +template +std::optional specialObjectsDequal(JSC__JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope* scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2); + template bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope* scope, bool addToStack) { @@ -728,15 +731,310 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, while (gcBuffer.size() > originalGCBufferSize) gcBuffer.removeLast(); } - }); + }); + + JSCell* c1 = v1.asCell(); + JSCell* c2 = v2.asCell(); + ASSERT(c1); + ASSERT(c2); + std::optional isSpecialEqual = specialObjectsDequal(globalObject, gcBuffer, stack, scope, c1, c2); + if (isSpecialEqual.has_value()) return std::move(*isSpecialEqual); + isSpecialEqual = specialObjectsDequal(globalObject, gcBuffer, stack, scope, c2, c1); + if (isSpecialEqual.has_value()) return std::move(*isSpecialEqual); + JSObject* o1 = v1.getObject(); + JSObject* o2 = v2.getObject(); + + bool v1Array = isArray(globalObject, v1); + RETURN_IF_EXCEPTION(*scope, false); + bool v2Array = isArray(globalObject, v2); + RETURN_IF_EXCEPTION(*scope, false); + + if (v1Array != v2Array) + return false; + + if (v1Array && v2Array) { + JSC::JSArray* array1 = JSC::jsCast(v1); + JSC::JSArray* array2 = JSC::jsCast(v2); + + size_t array1Length = array1->length(); + size_t array2Length = array2->length(); + if constexpr (isStrict) { + if (array1Length != array2Length) { + return false; + } + } + + uint64_t i = 0; + for (; i < array1Length; i++) { + JSValue left = getIndexWithoutAccessors(globalObject, o1, i); + RETURN_IF_EXCEPTION(*scope, false); + JSValue right = getIndexWithoutAccessors(globalObject, o2, i); + RETURN_IF_EXCEPTION(*scope, false); + + if constexpr (isStrict) { + if (left.isEmpty() && right.isEmpty()) { + continue; + } + if (left.isEmpty() || right.isEmpty()) { + return false; + } + } + + if constexpr (!isStrict) { + if (((left.isEmpty() || right.isEmpty()) && (left.isUndefined() || right.isUndefined()))) { + continue; + } + } + + if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { + return false; + } + + RETURN_IF_EXCEPTION(*scope, false); + } + + for (; i < array2Length; i++) { + JSValue right = getIndexWithoutAccessors(globalObject, o2, i); + RETURN_IF_EXCEPTION(*scope, false); + + if (((right.isEmpty() || right.isUndefined()))) { + continue; + } + + return false; + } + + JSC::PropertyNameArray a1(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArray a2(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); + JSObject::getOwnPropertyNames(o1, globalObject, a1, DontEnumPropertiesMode::Exclude); + JSObject::getOwnPropertyNames(o2, globalObject, a2, DontEnumPropertiesMode::Exclude); + + size_t propertyLength = a1.size(); + if constexpr (isStrict) { + if (propertyLength != a2.size()) { + return false; + } + } + + // take a property name from one, try to get it from both + for (size_t i = 0; i < propertyLength; i++) { + Identifier i1 = a1[i]; + PropertyName propertyName1 = PropertyName(i1); + + JSValue prop1 = o1->get(globalObject, propertyName1); + RETURN_IF_EXCEPTION(*scope, false); + + if (UNLIKELY(!prop1)) { + return false; + } + + JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName1); + RETURN_IF_EXCEPTION(*scope, false); + + if constexpr (!isStrict) { + if (prop1.isUndefined() && prop2.isEmpty()) { + continue; + } + } + + if (!prop2) { + return false; + } + + if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { + return false; + } + + RETURN_IF_EXCEPTION(*scope, false); + } + + RETURN_IF_EXCEPTION(*scope, false); + + return true; + } + + if constexpr (isStrict) { + if (!equal(JSObject::calculatedClassName(o1), JSObject::calculatedClassName(o2))) { + return false; + } + } + + JSC::Structure* o1Structure = o1->structure(); + if (!o1Structure->hasNonReifiedStaticProperties() && o1Structure->canPerformFastPropertyEnumeration()) { + JSC::Structure* o2Structure = o2->structure(); + if (!o2Structure->hasNonReifiedStaticProperties() && o2Structure->canPerformFastPropertyEnumeration()) { + + bool result = true; + bool sameStructure = o2Structure->id() == o1Structure->id(); + if (sameStructure) { + o1Structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { + if (entry.attributes() & PropertyAttribute::DontEnum || PropertyName(entry.key()).isPrivateName()) { + return true; + } + + JSValue left = o1->getDirect(entry.offset()); + JSValue right = o2->getDirect(entry.offset()); + + if constexpr (!isStrict) { + if (left.isUndefined() && right.isEmpty()) { + return true; + } + } + + if (!right) { + result = false; + return false; + } + + if (left == right || JSC::sameValue(globalObject, left, right)) { + return true; + } + + if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { + result = false; + return false; + } + + return true; + }); + } else { + size_t count = 0; + o1Structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { + if (entry.attributes() & PropertyAttribute::DontEnum || PropertyName(entry.key()).isPrivateName()) { + return true; + } + count++; + + JSValue left = o1->getDirect(entry.offset()); + JSValue right = o2->getDirect(vm, JSC::PropertyName(entry.key())); + + if constexpr (!isStrict) { + if (left.isUndefined() && right.isEmpty()) { + return true; + } + } + + if (!right) { + result = false; + return false; + } + + if (left == right || JSC::sameValue(globalObject, left, right)) { + return true; + } + + if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { + result = false; + return false; + } + + return true; + }); + + if (result) { + size_t remain = count; + o2Structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { + if (entry.attributes() & PropertyAttribute::DontEnum || PropertyName(entry.key()).isPrivateName()) { + return true; + } + + if constexpr (!isStrict) { + if (o2->getDirect(entry.offset()).isUndefined()) { + return true; + } + } + + // Try to get the right value from the left. We don't need to check if they're equal + // because the above loop has already iterated each property in the left. If we've + // seen this property before, it was already `deepEquals`ed. If it doesn't exist, + // the objects are not equal. + if (o1->getDirectOffset(vm, JSC::PropertyName(entry.key())) == invalidOffset) { + result = false; + return false; + } + + if (remain == 0) { + result = false; + return false; + } + + remain--; + return true; + }); + } + } + + return result; + } + } + + JSC::PropertyNameArray a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArray a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + o1->getPropertyNames(globalObject, a1, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(*scope, false); + o2->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(*scope, false); + + const size_t propertyArrayLength1 = a1.size(); + const size_t propertyArrayLength2 = a2.size(); + if constexpr (isStrict) { + if (propertyArrayLength1 != propertyArrayLength2) { + return false; + } + } + + // take a property name from one, try to get it from both + size_t i; + for (i = 0; i < propertyArrayLength1; i++) { + Identifier i1 = a1[i]; + PropertyName propertyName1 = PropertyName(i1); + + JSValue prop1 = o1->get(globalObject, propertyName1); + RETURN_IF_EXCEPTION(*scope, false); + + if (UNLIKELY(!prop1)) { + return false; + } + + JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName1); + RETURN_IF_EXCEPTION(*scope, false); + + if constexpr (!isStrict) { + if (prop1.isUndefined() && prop2.isEmpty()) { + continue; + } + } + + if (!prop2) { + return false; + } + + if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { + return false; + } + + RETURN_IF_EXCEPTION(*scope, false); + } + + // for the remaining properties in the other object, make sure they are undefined + for (; i < propertyArrayLength2; i++) { + Identifier i2 = a2[i]; + PropertyName propertyName2 = PropertyName(i2); + + JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName2); + RETURN_IF_EXCEPTION(*scope, false); + + if (!prop2.isUndefined()) { + return false; + } + } - JSCell* c1 = v1.asCell(); - JSCell* c2 = v2.asCell(); - JSObject* o1 = v1.getObject(); - JSObject* o2 = v2.getObject(); + return true; +} - // We use additional values outside the enum - // so the warning here is unnecessary +template +std::optional specialObjectsDequal(JSC__JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope* scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2) +{ uint8_t c1Type = c1->type(); uint8_t c2Type = c2->type(); @@ -829,8 +1127,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - JSC::ArrayBuffer* left = jsCast(v1)->impl(); - JSC::ArrayBuffer* right = jsCast(v2)->impl(); + JSC::ArrayBuffer* left = jsCast(c1)->impl(); + JSC::ArrayBuffer* right = jsCast(c2)->impl(); size_t byteLength = left->byteLength(); if (right->byteLength() != byteLength) { @@ -860,8 +1158,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - JSC::DateInstance* left = jsCast(v1); - JSC::DateInstance* right = jsCast(v2); + JSC::DateInstance* left = jsCast(c1); + JSC::DateInstance* right = jsCast(c2); return left->internalNumber() == right->internalNumber(); } @@ -870,8 +1168,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - if (JSC::RegExpObject* left = jsDynamicCast(v1)) { - JSC::RegExpObject* right = jsDynamicCast(v2); + if (JSC::RegExpObject* left = jsDynamicCast(c1)) { + JSC::RegExpObject* right = jsDynamicCast(c2); if (UNLIKELY(!right)) { return false; @@ -887,8 +1185,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - if (JSC::ErrorInstance* left = jsDynamicCast(v1)) { - JSC::ErrorInstance* right = jsDynamicCast(v2); + if (JSC::ErrorInstance* left = jsDynamicCast(c1)) { + JSC::ErrorInstance* right = jsDynamicCast(c2); if (UNLIKELY(!right)) { return false; @@ -914,8 +1212,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - JSC::JSArrayBufferView* left = jsCast(v1); - JSC::JSArrayBufferView* right = jsCast(v2); + JSC::JSArrayBufferView* left = jsCast(c1); + JSC::JSArrayBufferView* right = jsCast(c2); size_t byteLength = left->byteLength(); if (right->byteLength() != byteLength) { @@ -923,448 +1221,162 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, } if (byteLength == 0) - return true; - - if (UNLIKELY(right->isDetached() || left->isDetached())) { - return false; - } - - const void* vector = left->vector(); - const void* rightVector = right->vector(); - if (UNLIKELY(!vector || !rightVector)) { - return false; - } - - if (UNLIKELY(vector == rightVector)) - return true; - - return (memcmp(vector, rightVector, byteLength) == 0); - } - case StringObjectType: { - if (c2Type != StringObjectType) { - return false; - } - - if (!equal(JSObject::calculatedClassName(o1), JSObject::calculatedClassName(o2))) { - return false; - } - - JSString* s1 = c1->toStringInline(globalObject); - JSString* s2 = c2->toStringInline(globalObject); - - return s1->equal(globalObject, s2); - } - case JSFunctionType: { - return false; - } - - case JSAsJSONType: - case JSDOMWrapperType: { - if (c2Type == c1Type) { - - // https://github.com/oven-sh/bun/issues/4089 - // https://github.com/oven-sh/bun/issues/6492 - auto* url2 = jsDynamicCast(v2); - auto* url1 = jsDynamicCast(v1); - - if constexpr (isStrict) { - // if one is a URL and the other is not a URL, toStrictEqual returns false. - if ((url2 == nullptr) != (url1 == nullptr)) { - return false; - } - } else { - if ((url1 == nullptr) != (url2 == nullptr)) { - goto compareAsNormalValue; - } - } - - if (url2 && url1) { - // toEqual or toStrictEqual should return false when the URLs' href is not equal - // But you could have added additional properties onto the - // url object itself, so we must check those as well - // But it's definitely not equal if the href() is not the same - if (url1->wrapped().href() != url2->wrapped().href()) { - return false; - } - - goto compareAsNormalValue; - } - - // TODO: FormData. - // It's complicated because it involves Blob. - - { - auto urlSearchParams1 = jsDynamicCast(v1); - auto urlSearchParams2 = jsDynamicCast(v2); - if (urlSearchParams1 && urlSearchParams2) { - auto& wrapped1 = urlSearchParams1->wrapped(); - const auto& wrapped2 = urlSearchParams2->wrapped(); - if (wrapped1.size() != wrapped2.size()) { - return false; - } - - auto iter1 = wrapped1.createIterator(); - while (const auto& maybePair = iter1.next()) { - const auto& key = maybePair->key; - const auto& value = maybePair->value; - const auto& maybeValue = wrapped2.get(key); - if (!maybeValue || maybeValue != value) { - return false; - } - } - - goto compareAsNormalValue; - } else { - if constexpr (isStrict) { - // if one is a URLSearchParams and the other is not a URLSearchParams, toStrictEqual should return false. - if ((urlSearchParams2 == nullptr) != (urlSearchParams1 == nullptr)) { - return false; - } - } else { - if ((urlSearchParams1 == nullptr) != (urlSearchParams2 == nullptr)) { - goto compareAsNormalValue; - } - } - } - } - - { - auto headers1 = jsDynamicCast(v1); - auto headers2 = jsDynamicCast(v2); - if (headers1 && headers2) { - auto& wrapped1 = headers1->wrapped(); - const auto& wrapped2 = headers2->wrapped(); - if (wrapped1.size() != wrapped2.size()) { - return false; - } - - auto iter1 = wrapped1.createIterator(); - while (const auto& maybePair = iter1.next()) { - const auto& key = maybePair->key; - const auto& value = maybePair->value; - const auto& maybeValue = wrapped2.get(key); - if (maybeValue.hasException()) { - return false; - } - - if (maybeValue.returnValue() != value) { - return false; - } - } - - goto compareAsNormalValue; - } else { - if constexpr (isStrict) { - // if one is a FetchHeaders and the other is not a FetchHeaders, toStrictEqual should return false. - if ((headers2 == nullptr) != (headers1 == nullptr)) { - return false; - } - } else { - if ((headers1 == nullptr) != (headers2 == nullptr)) { - goto compareAsNormalValue; - } - } - } - } - } - - goto compareAsNormalValue; - - compareAsNormalValue: - break; - } - - default: { - break; - } - } - - bool v1Array = isArray(globalObject, v1); - RETURN_IF_EXCEPTION(*scope, false); - bool v2Array = isArray(globalObject, v2); - RETURN_IF_EXCEPTION(*scope, false); - - if (v1Array != v2Array) - return false; - - if (v1Array && v2Array) { - JSC::JSArray* array1 = JSC::jsCast(v1); - JSC::JSArray* array2 = JSC::jsCast(v2); - - size_t array1Length = array1->length(); - size_t array2Length = array2->length(); - if constexpr (isStrict) { - if (array1Length != array2Length) { - return false; - } - } - - uint64_t i = 0; - for (; i < array1Length; i++) { - JSValue left = getIndexWithoutAccessors(globalObject, o1, i); - RETURN_IF_EXCEPTION(*scope, false); - JSValue right = getIndexWithoutAccessors(globalObject, o2, i); - RETURN_IF_EXCEPTION(*scope, false); - - if constexpr (isStrict) { - if (left.isEmpty() && right.isEmpty()) { - continue; - } - if (left.isEmpty() || right.isEmpty()) { - return false; - } - } - - if constexpr (!isStrict) { - if (((left.isEmpty() || right.isEmpty()) && (left.isUndefined() || right.isUndefined()))) { - continue; - } - } - - if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { - return false; - } - - RETURN_IF_EXCEPTION(*scope, false); - } - - for (; i < array2Length; i++) { - JSValue right = getIndexWithoutAccessors(globalObject, o2, i); - RETURN_IF_EXCEPTION(*scope, false); - - if (((right.isEmpty() || right.isUndefined()))) { - continue; - } - - return false; - } - - JSC::PropertyNameArray a1(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); - JSC::PropertyNameArray a2(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); - JSObject::getOwnPropertyNames(o1, globalObject, a1, DontEnumPropertiesMode::Exclude); - JSObject::getOwnPropertyNames(o2, globalObject, a2, DontEnumPropertiesMode::Exclude); - - size_t propertyLength = a1.size(); - if constexpr (isStrict) { - if (propertyLength != a2.size()) { - return false; - } - } - - // take a property name from one, try to get it from both - for (size_t i = 0; i < propertyLength; i++) { - Identifier i1 = a1[i]; - PropertyName propertyName1 = PropertyName(i1); - - JSValue prop1 = o1->get(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); - - if (UNLIKELY(!prop1)) { - return false; - } - - JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); - - if constexpr (!isStrict) { - if (prop1.isUndefined() && prop2.isEmpty()) { - continue; - } - } - - if (!prop2) { - return false; - } + return true; - if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { - return false; - } + if (UNLIKELY(right->isDetached() || left->isDetached())) { + return false; + } - RETURN_IF_EXCEPTION(*scope, false); + const void* vector = left->vector(); + const void* rightVector = right->vector(); + if (UNLIKELY(!vector || !rightVector)) { + return false; } - RETURN_IF_EXCEPTION(*scope, false); + if (UNLIKELY(vector == rightVector)) + return true; - return true; + return (memcmp(vector, rightVector, byteLength) == 0); } + case StringObjectType: { + if (c2Type != StringObjectType) { + return false; + } - if constexpr (isStrict) { - if (!equal(JSObject::calculatedClassName(o1), JSObject::calculatedClassName(o2))) { + if (!equal(JSObject::calculatedClassName(c1->getObject()), JSObject::calculatedClassName(c2->getObject()))) { return false; } + + JSString* s1 = c1->toStringInline(globalObject); + JSString* s2 = c2->toStringInline(globalObject); + + return s1->equal(globalObject, s2); + } + case JSFunctionType: { + return false; } - JSC::Structure* o1Structure = o1->structure(); - if (!o1Structure->hasNonReifiedStaticProperties() && o1Structure->canPerformFastPropertyEnumeration()) { - JSC::Structure* o2Structure = o2->structure(); - if (!o2Structure->hasNonReifiedStaticProperties() && o2Structure->canPerformFastPropertyEnumeration()) { + case JSAsJSONType: + case JSDOMWrapperType: { + if (c2Type == c1Type) { - bool result = true; - bool sameStructure = o2Structure->id() == o1Structure->id(); - if (sameStructure) { - o1Structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { - if (entry.attributes() & PropertyAttribute::DontEnum || PropertyName(entry.key()).isPrivateName()) { - return true; - } + // https://github.com/oven-sh/bun/issues/4089 + // https://github.com/oven-sh/bun/issues/6492 + auto* url2 = jsDynamicCast(c2); + auto* url1 = jsDynamicCast(c1); - JSValue left = o1->getDirect(entry.offset()); - JSValue right = o2->getDirect(entry.offset()); + if constexpr (isStrict) { + // if one is a URL and the other is not a URL, toStrictEqual returns false. + if ((url2 == nullptr) != (url1 == nullptr)) { + return false; + } + } else { + if ((url1 == nullptr) != (url2 == nullptr)) { + goto compareAsNormalValue; + } + } - if constexpr (!isStrict) { - if (left.isUndefined() && right.isEmpty()) { - return true; - } - } + if (url2 && url1) { + // toEqual or toStrictEqual should return false when the URLs' href is not equal + // But you could have added additional properties onto the + // url object itself, so we must check those as well + // But it's definitely not equal if the href() is not the same + if (url1->wrapped().href() != url2->wrapped().href()) { + return false; + } - if (!right) { - result = false; - return false; - } + goto compareAsNormalValue; + } - if (left == right || JSC::sameValue(globalObject, left, right)) { - return true; - } + // TODO: FormData. + // It's complicated because it involves Blob. - if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { - result = false; + { + auto urlSearchParams1 = jsDynamicCast(c1); + auto urlSearchParams2 = jsDynamicCast(c2); + if (urlSearchParams1 && urlSearchParams2) { + auto& wrapped1 = urlSearchParams1->wrapped(); + const auto& wrapped2 = urlSearchParams2->wrapped(); + if (wrapped1.size() != wrapped2.size()) { return false; } - return true; - }); - } else { - size_t count = 0; - o1Structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { - if (entry.attributes() & PropertyAttribute::DontEnum || PropertyName(entry.key()).isPrivateName()) { - return true; - } - count++; - - JSValue left = o1->getDirect(entry.offset()); - JSValue right = o2->getDirect(vm, JSC::PropertyName(entry.key())); - - if constexpr (!isStrict) { - if (left.isUndefined() && right.isEmpty()) { - return true; + auto iter1 = wrapped1.createIterator(); + while (const auto& maybePair = iter1.next()) { + const auto& key = maybePair->key; + const auto& value = maybePair->value; + const auto& maybeValue = wrapped2.get(key); + if (!maybeValue || maybeValue != value) { + return false; } } - if (!right) { - result = false; - return false; - } - - if (left == right || JSC::sameValue(globalObject, left, right)) { - return true; + goto compareAsNormalValue; + } else { + if constexpr (isStrict) { + // if one is a URLSearchParams and the other is not a URLSearchParams, toStrictEqual should return false. + if ((urlSearchParams2 == nullptr) != (urlSearchParams1 == nullptr)) { + return false; + } + } else { + if ((urlSearchParams1 == nullptr) != (urlSearchParams2 == nullptr)) { + goto compareAsNormalValue; + } } + } + } - if (!Bun__deepEquals(globalObject, left, right, gcBuffer, stack, scope, true)) { - result = false; + { + auto headers1 = jsDynamicCast(c1); + auto headers2 = jsDynamicCast(c2); + if (headers1 && headers2) { + auto& wrapped1 = headers1->wrapped(); + const auto& wrapped2 = headers2->wrapped(); + if (wrapped1.size() != wrapped2.size()) { return false; } - return true; - }); - - if (result) { - size_t remain = count; - o2Structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { - if (entry.attributes() & PropertyAttribute::DontEnum || PropertyName(entry.key()).isPrivateName()) { - return true; - } - - if constexpr (!isStrict) { - if (o2->getDirect(entry.offset()).isUndefined()) { - return true; - } + auto iter1 = wrapped1.createIterator(); + while (const auto& maybePair = iter1.next()) { + const auto& key = maybePair->key; + const auto& value = maybePair->value; + const auto& maybeValue = wrapped2.get(key); + if (maybeValue.hasException()) { + return false; } - // Try to get the right value from the left. We don't need to check if they're equal - // because the above loop has already iterated each property in the left. If we've - // seen this property before, it was already `deepEquals`ed. If it doesn't exist, - // the objects are not equal. - if (o1->getDirectOffset(vm, JSC::PropertyName(entry.key())) == invalidOffset) { - result = false; + if (maybeValue.returnValue() != value) { return false; } + } - if (remain == 0) { - result = false; + goto compareAsNormalValue; + } else { + if constexpr (isStrict) { + // if one is a FetchHeaders and the other is not a FetchHeaders, toStrictEqual should return false. + if ((headers2 == nullptr) != (headers1 == nullptr)) { return false; } - - remain--; - return true; - }); + } else { + if ((headers1 == nullptr) != (headers2 == nullptr)) { + goto compareAsNormalValue; + } + } } } - - return result; } - } - JSC::PropertyNameArray a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); - JSC::PropertyNameArray a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); - o1->getPropertyNames(globalObject, a1, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); - o2->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); - RETURN_IF_EXCEPTION(*scope, false); + goto compareAsNormalValue; - const size_t propertyArrayLength1 = a1.size(); - const size_t propertyArrayLength2 = a2.size(); - if constexpr (isStrict) { - if (propertyArrayLength1 != propertyArrayLength2) { - return false; - } + compareAsNormalValue: + break; } - // take a property name from one, try to get it from both - size_t i; - for (i = 0; i < propertyArrayLength1; i++) { - Identifier i1 = a1[i]; - PropertyName propertyName1 = PropertyName(i1); - - JSValue prop1 = o1->get(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); - - if (UNLIKELY(!prop1)) { - return false; - } - - JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName1); - RETURN_IF_EXCEPTION(*scope, false); - - if constexpr (!isStrict) { - if (prop1.isUndefined() && prop2.isEmpty()) { - continue; - } - } - - if (!prop2) { - return false; - } - - if (!Bun__deepEquals(globalObject, prop1, prop2, gcBuffer, stack, scope, true)) { - return false; - } - - RETURN_IF_EXCEPTION(*scope, false); + default: { + break; } - - // for the remaining properties in the other object, make sure they are undefined - for (; i < propertyArrayLength2; i++) { - Identifier i2 = a2[i]; - PropertyName propertyName2 = PropertyName(i2); - - JSValue prop2 = o2->getIfPropertyExists(globalObject, propertyName2); - RETURN_IF_EXCEPTION(*scope, false); - - if (!prop2.isUndefined()) { - return false; - } } - - return true; + return std::nullopt; } /** @@ -1954,7 +1966,7 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, ASSERT_NO_PENDING_EXCEPTION(globalObject); SystemError err = *arg0; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue message = JSC::jsUndefined(); @@ -2018,7 +2030,7 @@ JSC__JSValue SystemError__toErrorInstanceWithInfoObject(const SystemError* arg0, ASSERT_NO_PENDING_EXCEPTION(globalObject); SystemError err = *arg0; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); @@ -2279,7 +2291,7 @@ JSC__JSPromise* JSC__JSValue__asPromise(JSC__JSValue JSValue0) JSC__JSValue JSC__JSValue__createInternalPromise(JSC__JSGlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); return JSC::JSValue::encode( JSC::JSValue(JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()))); } @@ -2372,7 +2384,7 @@ JSC__JSValue JSC__JSValue__parseJSON(JSC__JSValue JSValue0, JSC__JSGlobalObject* JSC__JSValue JSC__JSGlobalObject__getCachedObject(JSC__JSGlobalObject* globalObject, const ZigString* arg1) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); WTF::String string = Zig::toString(*arg1); auto symbol = vm.privateSymbolRegistry().symbolForKey(string); JSC::Identifier ident = JSC::Identifier::fromUid(symbol); @@ -2382,7 +2394,7 @@ JSC__JSValue JSC__JSGlobalObject__getCachedObject(JSC__JSGlobalObject* globalObj JSC__JSValue JSC__JSGlobalObject__putCachedObject(JSC__JSGlobalObject* globalObject, const ZigString* arg1, JSC__JSValue JSValue2) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); WTF::String string = Zig::toString(*arg1); auto symbol = vm.privateSymbolRegistry().symbolForKey(string); JSC::Identifier ident = JSC::Identifier::fromUid(symbol); @@ -2522,12 +2534,17 @@ bool JSC__JSValue__jestDeepMatch(JSC__JSValue JSValue0, JSC__JSValue JSValue1, J return Bun__deepMatch(obj, &objVisited, subset, &subsetVisited, globalObject, &scope, &gcBuffer, replacePropsWithAsymmetricMatchers, false); } +extern "C" bool Bun__JSValue__isAsyncContextFrame(JSC__JSValue value) +{ + return jsDynamicCast(JSValue::decode(value)) != nullptr; +} + extern "C" JSC__JSValue Bun__JSValue__call(JSContextRef ctx, JSC__JSValue object, JSC__JSValue thisObject, size_t argumentCount, const JSValueRef* arguments) { JSC::JSGlobalObject* globalObject = toJS(ctx); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ASSERT_WITH_MESSAGE(!vm.isCollectorBusyOnCurrentThread(), "Cannot call function inside a finalizer or while GC is running on same thread."); @@ -2581,7 +2598,7 @@ JSC__JSValue JSObjectCallAsFunctionReturnValueHoldingAPILock(JSContextRef ctx, J const JSValueRef* arguments) { JSC::JSGlobalObject* globalObject = toJS(ctx); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSLockHolder lock(vm); @@ -2686,7 +2703,7 @@ JSC__JSObject* JSC__JSString__toObject(JSC__JSString* arg0, JSC__JSGlobalObject* // } extern "C" JSC::JSInternalPromise* JSModuleLoader__import(JSC::JSGlobalObject* globalObject, const BunString* moduleNameStr) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* promise = JSC::importModule(globalObject, JSC::Identifier::fromString(vm, moduleNameStr->toWTFString()), jsUndefined(), jsUndefined(), jsUndefined()); @@ -2702,7 +2719,7 @@ JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* globalObject, co WTF::URL origin = WTF::URL::fileURLWithFileSystemPath(WTF::String::fromUTF8(std::span { originUrlPtr, originURLLen })).isolatedCopy(); WTF::URL referrer = WTF::URL::fileURLWithFileSystemPath(WTF::String::fromUTF8(std::span { referrerUrlPtr, referrerUrlLen })).isolatedCopy(); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::SourceCode sourceCode = JSC::makeSource( src, JSC::SourceOrigin { origin }, JSC::SourceTaintedOrigin::Untainted, origin.fileSystemPath(), @@ -2738,7 +2755,7 @@ static JSC::Identifier jsValueToModuleKey(JSC::JSGlobalObject* lexicalGlobalObje JSC__JSValue ReadableStream__empty(Zig::GlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto clientData = WebCore::clientData(vm); auto* function = globalObject->getDirect(vm, clientData->builtinNames().createEmptyReadableStreamPrivateName()).getObject(); return JSValue::encode(JSC::call(globalObject, function, JSC::ArgList(), "ReadableStream.create"_s)); @@ -2746,7 +2763,7 @@ JSC__JSValue ReadableStream__empty(Zig::GlobalObject* globalObject) JSC__JSValue ReadableStream__used(Zig::GlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto clientData = WebCore::clientData(vm); auto* function = globalObject->getDirect(vm, clientData->builtinNames().createUsedReadableStreamPrivateName()).getObject(); return JSValue::encode(JSC::call(globalObject, function, JSC::ArgList(), "ReadableStream.create"_s)); @@ -2755,7 +2772,7 @@ JSC__JSValue ReadableStream__used(Zig::GlobalObject* globalObject) JSC__JSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigString* arg1, JSC__JSGlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ZigString code = *arg1; JSC::JSObject* rangeError = Zig::getRangeErrorInstance(message, globalObject).asCell()->getObject(); @@ -2772,7 +2789,7 @@ JSC__JSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigS JSC__JSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigString* arg1, JSC__JSGlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ZigString code = *arg1; JSC::JSObject* typeError = Zig::getTypeErrorInstance(message, globalObject).asCell()->getObject(); @@ -2788,7 +2805,7 @@ JSC__JSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigSt JSC__JSValue JSC__JSValue__fromEntries(JSC__JSGlobalObject* globalObject, ZigString* keys, ZigString* values, size_t initialCapacity, bool clone) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (initialCapacity == 0) { return JSC::JSValue::encode(JSC::constructEmptyObject(globalObject)); @@ -2818,7 +2835,7 @@ JSC__JSValue JSC__JSValue__fromEntries(JSC__JSGlobalObject* globalObject, ZigStr JSC__JSValue JSC__JSValue__keys(JSC__JSGlobalObject* globalObject, JSC__JSValue objectValue) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); @@ -2830,7 +2847,7 @@ JSC__JSValue JSC__JSValue__keys(JSC__JSGlobalObject* globalObject, JSC__JSValue JSC__JSValue JSC__JSValue__values(JSC__JSGlobalObject* globalObject, JSC__JSValue objectValue) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue value = JSValue::decode(objectValue); return JSValue::encode(JSC::objectValues(vm, globalObject, value)); @@ -2941,7 +2958,7 @@ JSC__JSValue JSC__JSGlobalObject__createAggregateError(JSC__JSGlobalObject* glob const JSValue* errors, size_t errors_count, const ZigString* arg3) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue message = JSC::JSValue(JSC::jsOwnedString(vm, Zig::toString(*arg3))); @@ -2970,7 +2987,7 @@ JSC__JSValue JSC__JSGlobalObject__createAggregateError(JSC__JSGlobalObject* glob } JSC::EncodedJSValue JSC__JSGlobalObject__createAggregateErrorWithArray(JSC::JSGlobalObject* global, JSC::JSArray* array, BunString message, JSValue options) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); JSC::Structure* errorStructure = global->errorStructure(JSC::ErrorType::AggregateError); WTF::String messageString = message.toWTFString(); return JSC::JSValue::encode(JSC::createAggregateError(global, vm, errorStructure, array, JSC::jsString(vm, messageString), options, nullptr, JSC::TypeNothing, false)); @@ -3134,7 +3151,7 @@ JSC__JSInternalPromise* JSC__JSModuleLoader__loadAndEvaluateModule(JSC__JSGlobalObject* globalObject, const BunString* arg1) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto name = makeAtomString(arg1->toWTFString()); @@ -3164,7 +3181,7 @@ JSC__JSModuleLoader__loadAndEvaluateModule(JSC__JSGlobalObject* globalObject, void JSC__AnyPromise__wrap(JSC__JSGlobalObject* globalObject, EncodedJSValue encodedPromise, void* ctx, JSC__JSValue (*func)(void*, JSC__JSGlobalObject*)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); JSValue promiseValue = JSC::JSValue::decode(encodedPromise); @@ -3216,7 +3233,7 @@ void JSC__AnyPromise__wrap(JSC__JSGlobalObject* globalObject, EncodedJSValue enc JSC__JSValue JSC__JSPromise__wrap(JSC__JSGlobalObject* globalObject, void* ctx, JSC__JSValue (*func)(void*, JSC__JSGlobalObject*)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); JSValue result = JSC::JSValue::decode(func(ctx, globalObject)); @@ -3242,7 +3259,7 @@ void JSC__JSPromise__reject(JSC__JSPromise* arg0, JSC__JSGlobalObject* globalObj { JSValue value = JSC::JSValue::decode(JSValue2); ASSERT_WITH_MESSAGE(!value.isEmpty(), "Promise.reject cannot be called with a empty JSValue"); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ASSERT_WITH_MESSAGE(arg0->inherits(), "Argument is not a promise"); ASSERT_WITH_MESSAGE(arg0->status(vm) == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); @@ -3314,7 +3331,7 @@ void JSC__JSPromise__rejectOnNextTickWithHandled(JSC__JSPromise* promise, JSC__J JSC__JSValue encoedValue, bool handled) { JSC::JSValue value = JSC::JSValue::decode(encoedValue); - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); uint32_t flags = promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32(); if (!(flags & JSC::JSPromise::isFirstResolvingFunctionCalledFlag)) { @@ -3337,7 +3354,7 @@ void JSC__JSPromise__rejectOnNextTickWithHandled(JSC__JSPromise* promise, JSC__J JSC__JSPromise* JSC__JSPromise__resolvedPromise(JSC__JSGlobalObject* globalObject, JSC__JSValue JSValue1) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSPromise* promise = JSC::JSPromise::create(vm, globalObject->promiseStructure()); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast(JSC::JSPromise::Status::Fulfilled))); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, JSC::JSValue::decode(JSValue1)); @@ -3394,7 +3411,7 @@ void JSC__JSPromise__setHandled(JSC__JSPromise* promise, JSC__VM* arg1) JSC__JSInternalPromise* JSC__JSInternalPromise__create(JSC__JSGlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); return JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); } @@ -3402,7 +3419,7 @@ void JSC__JSInternalPromise__reject(JSC__JSInternalPromise* arg0, JSC__JSGlobalO JSC__JSValue JSValue2) { JSValue value = JSC::JSValue::decode(JSValue2); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::Exception* exception = nullptr; if (!value.inherits()) { exception = JSC::Exception::create(vm, value, JSC::Exception::StackCaptureAction::CaptureStack); @@ -3476,7 +3493,7 @@ void JSC__JSInternalPromise__setHandled(JSC__JSInternalPromise* promise, JSC__VM JSC__JSValue JSC__JSGlobalObject__generateHeapSnapshot(JSC__JSGlobalObject* globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSLockHolder lock(vm); // JSC::DeferTermination deferScope(vm); @@ -3561,7 +3578,7 @@ void JSC__JSValue__put(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, const Z extern "C" void JSC__JSValue__putMayBeIndex(JSC__JSValue target, JSC__JSGlobalObject* globalObject, const BunString* key, JSC__JSValue value) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); ThrowScope scope = DECLARE_THROW_SCOPE(vm); WTF::String keyStr = key->tag == BunStringTag::Empty ? WTF::String(""_s) : key->toWTFString(); @@ -3880,7 +3897,7 @@ JSC__JSValue JSC__JSValue__getIfPropertyExistsImpl(JSC__JSValue JSValue0, JSValue value = JSC::JSValue::decode(JSValue0); ASSERT_WITH_MESSAGE(!value.isEmpty(), "get() must not be called on empty value"); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* object = value.getObject(); if (UNLIKELY(!object)) { return JSValue::encode(JSValue::decode(JSC::JSValue::ValueDeleted)); @@ -4049,7 +4066,7 @@ void JSC__JSValue__getSymbolDescription(JSC__JSValue symbolValue_, JSC__JSGlobal JSC__JSValue JSC__JSValue__symbolFor(JSC__JSGlobalObject* globalObject, ZigString* arg2) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); WTF::String string = Zig::toString(*arg2); return JSC::JSValue::encode(JSC::Symbol::create(vm, vm.symbolRegistry().symbolForKey(string))); } @@ -4568,7 +4585,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, JSC::JSValue val, PopulateStackTraceFlags flags) { JSC::JSObject* obj = JSC::jsDynamicCast(val); - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); auto scope = DECLARE_CATCH_SCOPE(vm); bool getFromSourceURL = false; @@ -4768,7 +4785,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobalObject* global) { - JSC::VM& vm = global->vm(); + auto& vm = JSC::getVM(global); if (UNLIKELY(vm.hasPendingTerminationException())) { return; } @@ -4976,7 +4993,7 @@ extern "C" void JSC__JSValue__getName(JSC__JSValue JSValue0, JSC__JSGlobalObject *arg2 = BunStringEmpty; return; } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(globalObject->vm()); JSObject* object = value.getObject(); auto displayName = JSC::getCalculatedDisplayName(vm, object); @@ -5252,7 +5269,7 @@ void JSC__VM__throwError(JSC__VM* vm_, JSC__JSGlobalObject* arg1, JSC__JSValue e JSC__JSValue JSC__JSPromise__rejectedPromiseValue(JSC__JSGlobalObject* globalObject, JSC__JSValue JSValue1) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSPromise* promise = JSC::JSPromise::create(vm, globalObject->promiseStructure()); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast(JSC::JSPromise::Status::Rejected))); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, JSC::JSValue::decode(JSValue1)); @@ -5264,7 +5281,7 @@ JSC__JSValue JSC__JSPromise__rejectedPromiseValue(JSC__JSGlobalObject* globalObj JSC__JSValue JSC__JSPromise__resolvedPromiseValue(JSC__JSGlobalObject* globalObject, JSC__JSValue JSValue1) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSPromise* promise = JSC::JSPromise::create(vm, globalObject->promiseStructure()); promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast(JSC::JSPromise::Status::Fulfilled))); promise->internalField(JSC::JSPromise::Field::ReactionsOrResult).set(vm, promise, JSC::JSValue::decode(JSValue1)); @@ -5387,7 +5404,7 @@ JSC__JSValue JSC__JSValue__fastGet(JSC__JSValue JSValue0, JSC__JSGlobalObject* g JSC::JSObject* object = value.getObject(); ASSERT_WITH_MESSAGE(object, "fastGet() called on non-object. Check that the JSValue is an object before calling fastGet()."); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); const auto property = JSC::PropertyName(builtinNameMap(vm, arg2)); return JSC::JSValue::encode(Bun::getIfPropertyExistsPrototypePollutionMitigationUnsafe(vm, globalObject, object, property)); @@ -5428,7 +5445,7 @@ static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlob if (!object) return; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(!vm.isSafeToRecurse())) { @@ -5685,7 +5702,7 @@ void JSC__JSValue__forEachPropertyOrdered(JSC__JSValue JSValue0, JSC__JSGlobalOb if (!object) return; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); { @@ -5969,7 +5986,7 @@ CPP_DECL double JSC__JSValue__getUnixTimestamp(JSC__JSValue timeValue) extern "C" JSC::EncodedJSValue JSC__JSValue__getOwnByValue(JSC__JSValue value, JSC__JSGlobalObject* globalObject, JSC__JSValue propertyValue) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSObject* object = JSValue::decode(value).getObject(); JSC::JSValue property = JSValue::decode(propertyValue); @@ -5997,13 +6014,13 @@ extern "C" JSC::EncodedJSValue JSC__JSValue__getOwnByValue(JSC__JSValue value, J extern "C" double Bun__parseDate(JSC::JSGlobalObject* globalObject, BunString* str) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); return vm.dateCache.parseDate(globalObject, vm, str->toWTFString()); } extern "C" EncodedJSValue JSC__JSValue__dateInstanceFromNumber(JSC::JSGlobalObject* globalObject, double unixTimestamp) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::DateInstance* date = JSC::DateInstance::create(vm, globalObject->dateStructure(), unixTimestamp); return JSValue::encode(date); } @@ -6027,7 +6044,7 @@ extern "C" int JSC__JSValue__toISOString(JSC::JSGlobalObject* globalObject, Enco if (!std::isfinite(thisDateObj->internalNumber())) return -1; - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache); if (!gregorianDateTime) @@ -6061,7 +6078,7 @@ extern "C" int JSC__JSValue__DateNowISOString(JSC::JSGlobalObject* globalObject, if (!std::isfinite(thisDateObj->internalNumber())) return -1; - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(vm.dateCache); if (!gregorianDateTime) @@ -6171,6 +6188,11 @@ CPP_DECL void JSC__VM__setControlFlowProfiler(JSC__VM* vm, bool isEnabled) } } +CPP_DECL void JSC__VM__performOpportunisticallyScheduledTasks(JSC__VM* vm, double until) +{ + vm->performOpportunisticallyScheduledTasks(MonotonicTime::now() + Seconds(until), {}); +} + extern "C" EncodedJSValue JSC__createError(JSC::JSGlobalObject* globalObject, const BunString* str) { return JSValue::encode(JSC::createError(globalObject, str->toWTFString(BunString::ZeroCopy))); @@ -6304,7 +6326,7 @@ CPP_DECL bool Bun__CallFrame__isFromBunMain(JSC::CallFrame* callFrame, JSC::VM* CPP_DECL void Bun__CallFrame__getCallerSrcLoc(JSC::CallFrame* callFrame, JSC::JSGlobalObject* globalObject, BunString* outSourceURL, unsigned int* outLine, unsigned int* outColumn) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::LineColumn lineColumn; String sourceURL; @@ -6377,7 +6399,7 @@ extern "C" EncodedJSValue Bun__JSObject__getCodePropertyVMInquiry(JSC::JSGlobalO using StackCodeType = JSC::StackVisitor::Frame::CodeType; CPP_DECL bool Bun__util__isInsideNodeModules(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); bool inNodeModules = false; JSC::StackVisitor::visit(callFrame, vm, [&](JSC::StackVisitor& visitor) -> WTF::IterationStatus { if (Zig::isImplementationVisibilityPrivate(visitor) || visitor->isNativeCalleeFrame()) { diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 9c97513223bb62..f0a0fa6cc4f1d0 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -10,11 +10,9 @@ const ErrorableZigString = Exports.ErrorableZigString; const ErrorableResolvedSource = Exports.ErrorableResolvedSource; const ZigException = Exports.ZigException; const ZigStackTrace = Exports.ZigStackTrace; -const is_bindgen: bool = false; const ArrayBuffer = @import("../base.zig").ArrayBuffer; const JSC = bun.JSC; const Shimmer = JSC.Shimmer; -const ConsoleObject = JSC.ConsoleObject; const FFI = @import("./FFI.zig"); const NullableAllocator = bun.NullableAllocator; const MutableString = bun.MutableString; @@ -67,7 +65,7 @@ pub const JSObject = extern struct { /// prototype (`null_prototype = false`) unless you have a good reason not /// to. fn createFromStructWithPrototype(comptime T: type, pojo: T, global: *JSGlobalObject, comptime null_prototype: bool) *JSObject { - const info: std.builtin.Type.Struct = @typeInfo(T).Struct; + const info: std.builtin.Type.Struct = @typeInfo(T).@"struct"; const obj = obj: { const val = if (comptime null_prototype) @@ -194,7 +192,7 @@ pub const CachedBytecode = opaque { return null; } - extern "C" fn CachedBytecode__deref(this: *CachedBytecode) void; + extern "c" fn CachedBytecode__deref(this: *CachedBytecode) void; pub fn deref(this: *CachedBytecode) void { return CachedBytecode__deref(this); } @@ -612,7 +610,13 @@ pub const ZigString = extern struct { return !this.allocator.isNull(); } - pub fn clone(this: Slice, allocator: std.mem.Allocator) !Slice { + pub fn toOwned(this: Slice, allocator: std.mem.Allocator) OOM!Slice { + const duped = try allocator.dupe(u8, this.ptr[0..this.len]); + return .{ .allocator = .init(allocator), .ptr = duped.ptr, .len = this.len }; + } + + // TODO: this is identical to `cloneIfNeeded` + pub fn clone(this: Slice, allocator: std.mem.Allocator) OOM!Slice { if (this.isAllocated()) { return Slice{ .allocator = this.allocator, .ptr = this.ptr, .len = this.len }; } @@ -953,10 +957,10 @@ pub const ZigString = extern struct { }; } - pub fn toSliceClone(this: ZigString, allocator: std.mem.Allocator) Slice { + pub fn toSliceClone(this: ZigString, allocator: std.mem.Allocator) OOM!Slice { if (this.len == 0) return Slice.empty; - const buffer = this.toOwnedSlice(allocator) catch unreachable; + const buffer = try this.toOwnedSlice(allocator); return Slice{ .allocator = NullableAllocator.init(allocator), .ptr = buffer.ptr, @@ -1334,7 +1338,7 @@ pub const FetchHeaders = opaque { }); } - extern "C" fn WebCore__FetchHeaders__createFromJS(*JSC.JSGlobalObject, JSValue) ?*FetchHeaders; + extern "c" fn WebCore__FetchHeaders__createFromJS(*JSC.JSGlobalObject, JSValue) ?*FetchHeaders; /// Construct a `Headers` object from a JSValue. /// /// This can be: @@ -1985,7 +1989,7 @@ pub const JSString = extern struct { this: *JSString, global: *JSGlobalObject, allocator: std.mem.Allocator, - ) ZigString.Slice { + ) JSError!ZigString.Slice { var str = ZigString.init(""); this.toZigString(global, &str); return str.toSliceClone(allocator); @@ -2535,7 +2539,7 @@ pub const JSPromise = extern struct { const Wrapper = struct { args: Args, - pub fn call(this: *@This(), g: *JSC.JSGlobalObject) JSC.JSValue { + pub fn call(this: *@This(), g: *JSC.JSGlobalObject) callconv(.c) JSC.JSValue { return toJSHostValue(g, @call(.auto, Fn, this.args)); } }; @@ -2816,7 +2820,7 @@ pub const AnyPromise = union(enum) { const Wrapper = struct { args: Args, - pub fn call(wrap_: *@This(), global: *JSC.JSGlobalObject) JSC.JSValue { + pub fn call(wrap_: *@This(), global: *JSC.JSGlobalObject) callconv(.c) JSC.JSValue { return toJSHostValue(global, @call(.auto, Fn, wrap_.args)); } }; @@ -2995,7 +2999,7 @@ pub const JSGlobalObject = opaque { return this.ERR_INVALID_ARG_VALUE("The \"{s}\" argument is invalid. Received {}", .{ argname, actual_string_value }).throw(); } - extern "C" fn Bun__ErrorCode__determineSpecificType(*JSGlobalObject, JSValue) String; + extern "c" fn Bun__ErrorCode__determineSpecificType(*JSGlobalObject, JSValue) String; pub fn determineSpecificType(global: *JSGlobalObject, value: JSValue) JSError!String { const str = Bun__ErrorCode__determineSpecificType(global, value); @@ -3801,7 +3805,7 @@ pub const JSValue = enum(i64) { }; } - pub fn isTypedArray(this: JSType) bool { + pub fn isTypedArrayOrArrayBuffer(this: JSType) bool { return switch (this) { .ArrayBuffer, .BigInt64Array, @@ -4085,7 +4089,6 @@ pub const JSValue = enum(i64) { if (this.isDouble()) { return this.asDouble(); } - return this.coerceToDouble(globalThis); }, i64 => { @@ -4095,13 +4098,21 @@ pub const JSValue = enum(i64) { if (this.isInt32()) { return this.asInt32(); } - if (this.getNumber()) |num| { return coerceJSValueDoubleTruncatingT(i32, num); } - return this.coerceToInt32(globalThis); }, + std.c.AI, + => { + if (this.isInt32()) { + return @bitCast(this.asInt32()); + } + if (this.getNumber()) |num| { + return @bitCast(coerceJSValueDoubleTruncatingT(i32, num)); + } + return @bitCast(this.coerceToInt32(globalThis)); + }, else => @compileError("Unsupported coercion type"), }; } @@ -4109,8 +4120,8 @@ pub const JSValue = enum(i64) { /// This does not call [Symbol.toPrimitive] or [Symbol.toStringTag]. /// This is only safe when you don't want to do conversions across non-primitive types. pub fn to(this: JSValue, comptime T: type) T { - if (@typeInfo(T) == .Enum) { - const Int = @typeInfo(T).Enum.tag_type; + if (@typeInfo(T) == .@"enum") { + const Int = @typeInfo(T).@"enum".tag_type; return @enumFromInt(this.to(Int)); } return switch (comptime T) { @@ -4179,7 +4190,9 @@ pub const JSValue = enum(i64) { loop.debug.last_fn_name.deref(); loop.debug.last_fn_name = function.getName(global); } - bun.assert(function.isCallable(global.vm())); + // Do not assert that the function is callable here. + // The Bun__JSValue__call function will already assert that, and + // this can be an async context so it's fine if it's not callable. } return Bun__JSValue__call( @@ -4238,7 +4251,7 @@ pub const JSValue = enum(i64) { @import("./headers.zig").JSC__JSValue__put(value, global, key, result); } - extern "C" fn JSC__JSValue__putBunString(value: JSValue, global: *JSGlobalObject, key: *const bun.String, result: JSC.JSValue) void; + extern "c" fn JSC__JSValue__putBunString(value: JSValue, global: *JSGlobalObject, key: *const bun.String, result: JSC.JSValue) void; fn putBunString(value: JSValue, global: *JSGlobalObject, key: *const bun.String, result: JSC.JSValue) void { if (comptime bun.Environment.isDebug) JSC.markBinding(@src()); @@ -4247,8 +4260,8 @@ pub const JSValue = enum(i64) { pub fn put(value: JSValue, global: *JSGlobalObject, key: anytype, result: JSC.JSValue) void { const Key = @TypeOf(key); - if (comptime @typeInfo(Key) == .Pointer) { - const Elem = @typeInfo(Key).Pointer.child; + if (comptime @typeInfo(Key) == .pointer) { + const Elem = @typeInfo(Key).pointer.child; if (Elem == ZigString) { putZigString(value, global, key, result); } else if (Elem == bun.String) { @@ -4475,8 +4488,8 @@ pub const JSValue = enum(i64) { extern fn JSBuffer__bufferFromPointerAndLengthAndDeinit(*JSGlobalObject, [*]u8, usize, ?*anyopaque, JSC.C.JSTypedArrayBytesDeallocator) JSValue; pub fn jsNumberWithType(comptime Number: type, number: Number) JSValue { - if (@typeInfo(Number) == .Enum) { - return jsNumberWithType(@typeInfo(Number).Enum.tag_type, @intFromEnum(number)); + if (@typeInfo(Number) == .@"enum") { + return jsNumberWithType(@typeInfo(Number).@"enum".tag_type, @intFromEnum(number)); } return switch (comptime Number) { JSValue => number, @@ -4569,8 +4582,8 @@ pub const JSValue = enum(i64) { pub fn print( this: JSValue, globalObject: *JSGlobalObject, - message_type: ConsoleObject.MessageType, - message_level: ConsoleObject.MessageLevel, + message_type: JSC.ConsoleObject.MessageType, + message_level: JSC.ConsoleObject.MessageLevel, ) void { JSC.ConsoleObject.messageWithTypeAndLevel( undefined, @@ -4637,7 +4650,7 @@ pub const JSValue = enum(i64) { }); } - extern "C" fn JSC__JSValue__hasOwnPropertyValue(JSValue, *JSGlobalObject, JSValue) bool; + extern "c" fn JSC__JSValue__hasOwnPropertyValue(JSValue, *JSGlobalObject, JSValue) bool; /// Calls `Object.hasOwnProperty(value)`. /// Returns true if the object has the property, false otherwise /// @@ -5022,27 +5035,9 @@ pub const JSValue = enum(i64) { return str; } - /// Convert a JSValue to a string, potentially calling `toString` on the - /// JSValue in JavaScript. - /// - /// This function can throw an exception in the `JSC::VM`. **If - /// the exception is not handled correctly, Bun will segfault** - /// - /// To handle exceptions, use `JSValue.toSliceOrNull`. - pub inline fn toSlice(this: JSValue, global: *JSGlobalObject, allocator: std.mem.Allocator) ZigString.Slice { - const str = bun.String.fromJS(this, global); - defer str.deref(); - - // This keeps the WTF::StringImpl alive if it was originally a latin1 - // ASCII-only string. - // - // Otherwise, it will be cloned using the allocator. - return str.toUTF8(allocator); - } - /// Convert a JSValue to a string, potentially calling `toString` on the /// JSValue in JavaScript. Can throw an error. - pub fn toSlice2(this: JSValue, global: *JSGlobalObject, allocator: std.mem.Allocator) JSError!ZigString.Slice { + pub fn toSlice(this: JSValue, global: *JSGlobalObject, allocator: std.mem.Allocator) JSError!ZigString.Slice { const str = try bun.String.fromJS2(this, global); defer str.deref(); @@ -5348,7 +5343,7 @@ pub const JSValue = enum(i64) { return getOwnTruthy(this, global, property); } - pub fn truthyPropertyValue(prop: JSValue) ?JSValue { + fn truthyPropertyValue(prop: JSValue) ?JSValue { return switch (prop) { .zero => unreachable, @@ -6145,6 +6140,10 @@ pub const JSValue = enum(i64) { return AsyncContextFrame__withAsyncContextIfNeeded(global, this); } + pub fn isAsyncContextFrame(this: JSValue) bool { + return Bun__JSValue__isAsyncContextFrame(this); + } + extern "c" fn Bun__JSValue__deserialize(global: *JSGlobalObject, data: [*]const u8, len: usize) JSValue; /// Deserializes a JSValue from a serialized buffer. Zig version of `import('bun:jsc').deserialize` @@ -6205,6 +6204,7 @@ pub const JSValue = enum(i64) { }; extern "c" fn AsyncContextFrame__withAsyncContextIfNeeded(global: *JSGlobalObject, callback: JSValue) JSValue; +extern "c" fn Bun__JSValue__isAsyncContextFrame(value: JSValue) bool; pub const VM = extern struct { pub const shim = Shimmer("JSC", "VM", @This()); @@ -6221,22 +6221,6 @@ pub const VM = extern struct { LargeHeap = 1, }; - extern fn Bun__JSC_onBeforeWait(vm: *VM) i32; - extern fn Bun__JSC_onAfterWait(vm: *VM) void; - pub const ReleaseHeapAccess = struct { - vm: *VM, - needs_to_release: bool, - pub fn acquire(this: *const ReleaseHeapAccess) void { - if (this.needs_to_release) { - Bun__JSC_onAfterWait(this.vm); - } - } - }; - - pub fn releaseHeapAccess(vm: *VM) ReleaseHeapAccess { - return .{ .vm = vm, .needs_to_release = Bun__JSC_onBeforeWait(vm) != 0 }; - } - pub fn create(heap_type: HeapType) *VM { return cppFn("create", .{@intFromEnum(heap_type)}); } @@ -6397,6 +6381,10 @@ pub const VM = extern struct { return cppFn("blockBytesAllocated", .{vm}); } + pub fn performOpportunisticallyScheduledTasks(vm: *VM, until: f64) void { + cppFn("performOpportunisticallyScheduledTasks", .{ vm, until }); + } + pub const Extern = [_][]const u8{ "setControlFlowProfiler", "collectAsync", diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 66906609504224..c94b5e7b9e0263 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -1,7 +1,6 @@ const JSC = bun.JSC; const Fs = @import("../../fs.zig"); const CAPI = JSC.C; -const JS = @import("../javascript.zig"); const JSBase = @import("../base.zig"); const ZigURL = @import("../../url.zig").URL; const Api = @import("../../api/schema.zig").Api; @@ -12,7 +11,6 @@ const strings = bun.strings; const default_allocator = bun.default_allocator; const NewGlobalObject = JSC.NewGlobalObject; const JSGlobalObject = JSC.JSGlobalObject; -const is_bindgen: bool = false; const ZigString = JSC.ZigString; const string = bun.string; const JSValue = JSC.JSValue; @@ -49,15 +47,17 @@ pub const ZigGlobalObject = extern struct { pub const name = "Zig::GlobalObject"; pub const include = "\"ZigGlobalObject.h\""; pub const namespace = shim.namespace; - pub const Interface: type = NewGlobalObject(JS.VirtualMachine); + pub const Interface: type = NewGlobalObject(JSC.VirtualMachine); pub fn create( + vm: *JSC.VirtualMachine, console: *anyopaque, context_id: i32, mini_mode: bool, eval_mode: bool, worker_ptr: ?*anyopaque, ) *JSGlobalObject { + vm.eventLoop().ensureWaker(); const global = shim.cppFn("create", .{ console, context_id, mini_mode, eval_mode, worker_ptr }); // JSC might mess with the stack size. @@ -112,11 +112,11 @@ pub const ZigGlobalObject = extern struct { pub const Extern = [_][]const u8{ "create", "getModuleRegistryMap", "resetModuleRegistryMap" }; comptime { - @export(import, .{ .name = Export[0].symbol_name }); - @export(resolve, .{ .name = Export[1].symbol_name }); - @export(promiseRejectionTracker, .{ .name = Export[2].symbol_name }); - @export(reportUncaughtException, .{ .name = Export[3].symbol_name }); - @export(onCrash, .{ .name = Export[4].symbol_name }); + @export(&import, .{ .name = Export[0].symbol_name }); + @export(&resolve, .{ .name = Export[1].symbol_name }); + @export(&promiseRejectionTracker, .{ .name = Export[2].symbol_name }); + @export(&reportUncaughtException, .{ .name = Export[3].symbol_name }); + @export(&onCrash, .{ .name = Export[4].symbol_name }); } }; @@ -224,7 +224,7 @@ pub const ResolvedSource = extern struct { allocator: ?*anyopaque = null, - jsvalue_for_export: JSC.JSValue = .zero, + jsvalue_for_export: JSValue = .zero, tag: Tag = Tag.javascript, @@ -412,36 +412,33 @@ pub const Process = extern struct { }); comptime { - if (!is_bindgen) { - @export(getTitle, .{ - .name = Export[0].symbol_name, - }); - @export(setTitle, .{ - .name = Export[1].symbol_name, - }); - @export(getArgv, .{ - .name = Export[2].symbol_name, - }); - @export(getCwd, .{ - .name = Export[3].symbol_name, - }); - @export(setCwd, .{ - .name = Export[4].symbol_name, - }); - @export(exit, .{ - .name = Export[5].symbol_name, - }); - @export(getArgv0, .{ - .name = Export[6].symbol_name, - }); - @export(getExecPath, .{ - .name = Export[7].symbol_name, - }); - - @export(getExecArgv, .{ - .name = Export[8].symbol_name, - }); - } + @export(&getTitle, .{ + .name = Export[0].symbol_name, + }); + @export(&setTitle, .{ + .name = Export[1].symbol_name, + }); + @export(&getArgv, .{ + .name = Export[2].symbol_name, + }); + @export(&getCwd, .{ + .name = Export[3].symbol_name, + }); + @export(&setCwd, .{ + .name = Export[4].symbol_name, + }); + @export(&exit, .{ + .name = Export[5].symbol_name, + }); + @export(&getArgv0, .{ + .name = Export[6].symbol_name, + }); + @export(&getExecPath, .{ + .name = Export[7].symbol_name, + }); + @export(&getExecArgv, .{ + .name = Export[8].symbol_name, + }); } }; @@ -839,7 +836,6 @@ pub const ZigException = extern struct { } pub const shim = Shimmer("Zig", "Exception", @This()); - pub const name = "ZigException"; pub const namespace = shim.namespace; pub const Holder = extern struct { @@ -968,8 +964,8 @@ pub inline fn toGlobalContextRef(ptr: *JSGlobalObject) CAPI.JSGlobalContextRef { } comptime { - @export(ErrorCode.ParserError, .{ .name = "Zig_ErrorCodeParserError" }); - @export(ErrorCode.JSErrorObject, .{ .name = "Zig_ErrorCodeJSErrorObject" }); + @export(&ErrorCode.ParserError, .{ .name = "Zig_ErrorCodeParserError" }); + @export(&ErrorCode.JSErrorObject, .{ .name = "Zig_ErrorCodeJSErrorObject" }); } const Bun = JSC.API.Bun; @@ -982,34 +978,32 @@ pub const HTTPDebugSSLServerRequestContext = JSC.API.DebugHTTPSServer.RequestCon pub const BodyValueBuffererContext = JSC.WebCore.BodyValueBufferer; pub const TestScope = @import("../test/jest.zig").TestScope; comptime { - if (!is_bindgen) { - WebSocketHTTPClient.shim.ref(); - WebSocketHTTPSClient.shim.ref(); - WebSocketClient.shim.ref(); - WebSocketClientTLS.shim.ref(); - - HTTPServerRequestContext.shim.ref(); - HTTPSSLServerRequestContext.shim.ref(); - HTTPDebugServerRequestContext.shim.ref(); - HTTPDebugSSLServerRequestContext.shim.ref(); - - _ = Process.getTitle; - _ = Process.setTitle; - NodePath.shim.ref(); - JSArrayBufferSink.shim.ref(); - JSHTTPResponseSink.shim.ref(); - JSHTTPSResponseSink.shim.ref(); - JSNetworkSink.shim.ref(); - JSFileSink.shim.ref(); - JSFileSink.shim.ref(); - _ = ZigString__free; - _ = ZigString__free_global; - - TestScope.shim.ref(); - BodyValueBuffererContext.shim.ref(); - - _ = Bun__LoadLibraryBunString; - } + WebSocketHTTPClient.shim.ref(); + WebSocketHTTPSClient.shim.ref(); + WebSocketClient.shim.ref(); + WebSocketClientTLS.shim.ref(); + + HTTPServerRequestContext.shim.ref(); + HTTPSSLServerRequestContext.shim.ref(); + HTTPDebugServerRequestContext.shim.ref(); + HTTPDebugSSLServerRequestContext.shim.ref(); + + _ = Process.getTitle; + _ = Process.setTitle; + NodePath.shim.ref(); + JSArrayBufferSink.shim.ref(); + JSHTTPResponseSink.shim.ref(); + JSHTTPSResponseSink.shim.ref(); + JSNetworkSink.shim.ref(); + JSFileSink.shim.ref(); + JSFileSink.shim.ref(); + _ = ZigString__free; + _ = ZigString__free_global; + + TestScope.shim.ref(); + BodyValueBuffererContext.shim.ref(); + + _ = Bun__LoadLibraryBunString; } /// Returns null on error. Use windows API to lookup the actual error. diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig index e6d8da866c48f0..d179e7059b1a55 100644 --- a/src/bun.js/bindings/generated_classes_list.zig +++ b/src/bun.js/bindings/generated_classes_list.zig @@ -12,7 +12,6 @@ pub const Classes = struct { pub const EndTag = JSC.Cloudflare.EndTag; pub const AttributeIterator = JSC.Cloudflare.AttributeIterator; pub const CryptoHasher = JSC.API.Bun.Crypto.CryptoHasher; - pub const Dirent = JSC.Node.Dirent; pub const Expect = JSC.Expect.Expect; pub const ExpectAny = JSC.Expect.ExpectAny; pub const ExpectAnything = JSC.Expect.ExpectAnything; @@ -47,8 +46,6 @@ pub const Classes = struct { pub const SHA512 = JSC.API.Bun.Crypto.SHA512; pub const SHA512_256 = JSC.API.Bun.Crypto.SHA512_256; pub const ServerWebSocket = JSC.API.ServerWebSocket; - pub const Stats = JSC.Node.StatsSmall; - pub const BigIntStats = JSC.Node.StatsBig; pub const Subprocess = JSC.Subprocess; pub const ResourceUsage = JSC.ResourceUsage; pub const TCPSocket = JSC.API.TCPSocket; diff --git a/src/bun.js/bindings/header-gen.zig b/src/bun.js/bindings/header-gen.zig index 3b4dd7ca1ba808..14a8eac7b77fc0 100644 --- a/src/bun.js/bindings/header-gen.zig +++ b/src/bun.js/bindings/header-gen.zig @@ -156,8 +156,8 @@ pub const C_Generator = struct { comptime nonnull.append(i) catch unreachable; }, else => |info| { - if (comptime info == .Pointer and @typeInfo(info.Pointer.child) == .Fn) { - self.gen_closure(comptime info.Pointer.child, comptime std.fmt.comptimePrint(" ArgFn{d}", .{i})); + if (comptime info == .pointer and @typeInfo(info.pointer.child) == .Fn) { + self.gen_closure(comptime info.pointer.child, comptime std.fmt.comptimePrint(" ArgFn{d}", .{i})); comptime nonnull.append(i) catch unreachable; } else { self.writeType(comptime arg.type.?); @@ -189,7 +189,7 @@ pub const C_Generator = struct { defer self.write(";\n"); // const ReturnTypeInfo: std.builtin.Type = comptime @typeInfo(func.return_type); // switch (comptime ReturnTypeInfo) { - // .Pointer => |Pointer| { + // .pointer => |Pointer| { // self.write(" __attribute__((returns_nonnull))"); // }, // .Optional => |Optional| {}, @@ -226,7 +226,7 @@ pub const C_Generator = struct { self.write(")"); // const ReturnTypeInfo: std.builtin.Type = comptime @typeInfo(func.return_type); // switch (comptime ReturnTypeInfo) { - // .Pointer => |Pointer| { + // .pointer => |Pointer| { // self.write(" __attribute__((returns_nonnull))"); // }, // .Optional => |Optional| {}, @@ -344,16 +344,16 @@ pub const C_Generator = struct { Type = OtherType; } } - if (@typeInfo(Type) == .Pointer and !std.meta.isManyItemPtr(Type)) { - Type = @typeInfo(Type).Pointer.child; + if (@typeInfo(Type) == .pointer and !std.meta.isManyItemPtr(Type)) { + Type = @typeInfo(Type).pointer.child; } break :brk Type; }; if (comptime (isCppObject(TT)) and @hasDecl(TT, "name")) { - if (@typeInfo(T) == .Pointer or (@hasDecl(TT, "Type") and (@TypeOf(TT.Type) == type and @typeInfo(TT.Type) == .Pointer))) { - if (@hasDecl(TT, "is_pointer") and !TT.is_pointer) {} else if (@typeInfo(T).Pointer.is_const) { + if (@typeInfo(T) == .pointer or (@hasDecl(TT, "Type") and (@TypeOf(TT.Type) == type and @typeInfo(TT.Type) == .pointer))) { + if (@hasDecl(TT, "is_pointer") and !TT.is_pointer) {} else if (@typeInfo(T).pointer.is_const) { write(self, "const "); } } @@ -401,7 +401,7 @@ pub const C_Generator = struct { write(self, comptime formatted_name); } - if (@typeInfo(T) == .Pointer or (@hasDecl(TT, "Type") and (@TypeOf(TT.Type) == type and @typeInfo(TT.Type) == .Pointer))) { + if (@typeInfo(T) == .pointer or (@hasDecl(TT, "Type") and (@TypeOf(TT.Type) == type and @typeInfo(TT.Type) == .pointer))) { if (@hasDecl(TT, "is_pointer") and !TT.is_pointer) {} else { write(self, "*"); } @@ -414,7 +414,7 @@ pub const C_Generator = struct { } else { const meta = @typeInfo(T); switch (meta) { - .Pointer => |Pointer| { + .pointer => |Pointer| { const child = Pointer.child; // if (childmeta == .Struct and childmeta.Struct.layout != .Extern) { // self.write("void"); @@ -619,9 +619,9 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp \\//-- GENERATED FILE. Do not edit -- \\// \\// To regenerate this file, run: - \\// + \\// \\// make headers - \\// + \\// \\//-- GENERATED FILE. Do not edit -- \\ ) catch unreachable; @@ -663,9 +663,9 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp \\//-- GENERATED FILE. Do not edit -- \\// \\// To regenerate this file, run: - \\// + \\// \\// make headers - \\// + \\// \\//-- GENERATED FILE. Do not edit -- \\ ) catch unreachable; @@ -726,8 +726,8 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp all_types[1] = second_import; var counter: usize = 2; inline for (first_import.DOMCalls) |Type_| { - const Type = if (@typeInfo(@TypeOf(Type_)) == .Pointer) - @typeInfo(@TypeOf(Type_)).Pointer.child + const Type = if (@typeInfo(@TypeOf(Type_)) == .pointer) + @typeInfo(@TypeOf(Type_)).pointer.child else @TypeOf(Type_); @@ -742,8 +742,8 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp }; inline for (first_import.DOMCalls) |Type_| { - const Type = if (@typeInfo(@TypeOf(Type_)) == .Pointer) - @typeInfo(@TypeOf(Type_)).Pointer.child + const Type = if (@typeInfo(@TypeOf(Type_)) == .pointer) + @typeInfo(@TypeOf(Type_)).pointer.child else @TypeOf(Type_); @@ -962,16 +962,16 @@ pub fn HeaderGen(comptime first_import: type, comptime second_import: type, comp generated.writer().print( \\ #include "root.h" \\ #include "headers.h" - \\ + \\ \\ #include \\ #include "DOMJITIDLConvert.h" \\ #include "DOMJITIDLType.h" \\ #include "DOMJITIDLTypeFilter.h" \\ #include "DOMJITHelpers.h" \\ #include - \\ + \\ \\ #include "JSDOMConvertBufferSource.h" - \\ + \\ \\ using namespace JSC; \\ using namespace WebCore; \\ diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 4da107cbbdf1d9..9a81eda9783d81 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -69,6 +69,8 @@ typedef struct BunString { // It's only truly zero-copy if it was already a WTFStringImpl (which it is if it came from JS and we didn't use ZigString) WTF::String toWTFString(ZeroCopyTag) const; + WTF::String transferToWTFString(); + // This one usually will clone the raw bytes. WTF::String toWTFString() const; diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig index 2f0bbc3205a0d6..b2b777ab027ebf 100644 --- a/src/bun.js/bindings/headers.zig +++ b/src/bun.js/bindings/headers.zig @@ -313,7 +313,7 @@ pub extern fn JSC__VM__setExecutionTimeLimit(arg0: *bindings.VM, arg1: f64) void pub extern fn JSC__VM__shrinkFootprint(arg0: *bindings.VM) void; pub extern fn JSC__VM__throwError(arg0: *bindings.VM, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) void; pub extern fn JSC__VM__whenIdle(arg0: *bindings.VM, ArgFn1: ?*const fn (...) callconv(.C) void) void; - +pub extern fn JSC__VM__performOpportunisticallyScheduledTasks(arg0: *bindings.VM, arg1: f64) void; pub extern fn FFI__ptr__put(arg0: *bindings.JSGlobalObject, JSValue1: JSC__JSValue) void; pub extern fn Reader__u8__put(arg0: *bindings.JSGlobalObject, JSValue1: JSC__JSValue) void; pub extern fn Reader__u16__put(arg0: *bindings.JSGlobalObject, JSValue1: JSC__JSValue) void; diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index 2653138c7903a8..47188d9a772920 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -82,6 +82,7 @@ static const WTF::String toString(ZigString str) return WTF::String(); } if (UNLIKELY(isTaggedUTF8Ptr(str.ptr))) { + ASSERT_WITH_MESSAGE(!isTaggedExternalPtr(str.ptr), "UTF8 and external ptr are mutually exclusive. The external will never be freed."); return WTF::String::fromUTF8ReplacingInvalidSequences(std::span { untag(str.ptr), str.len }); } diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index b2a849ea725edd..bd028319ffef53 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -565,7 +565,7 @@ class NAPIFunction : public JSC::JSFunction { auto* env = toNapi(globalObject); ASSERT(function->m_method); auto* callback = reinterpret_cast(function->m_method); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); MarkedArgumentBufferWithSize<12> args; size_t argc = callframe->argumentCount() + 1; @@ -634,7 +634,7 @@ Structure* Zig::createNAPIFunctionStructure(VM& vm, JSC::JSGlobalObject* globalO static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* to, void* inheritedDataPtr, napi_property_descriptor property, bool isInstance, JSC::ThrowScope& scope) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); void* dataPtr = property.data; if (!dataPtr) { dataPtr = inheritedDataPtr; @@ -850,7 +850,7 @@ extern "C" napi_status napi_set_named_property(napi_env env, napi_value object, NAPI_CHECK_ARG(env, value); auto globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto target = toJS(object).toObject(globalObject); NAPI_RETURN_IF_EXCEPTION(env); @@ -876,7 +876,7 @@ extern "C" napi_status napi_create_arraybuffer(napi_env env, NAPI_CHECK_ARG(env, result); Zig::GlobalObject* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); // Node probably doesn't create uninitialized array buffers // but the node-api docs don't specify whether memory is initialized or not. @@ -895,6 +895,30 @@ extern "C" napi_status napi_create_arraybuffer(napi_env env, NAPI_RETURN_SUCCESS(env); } +extern "C" napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) +{ + NAPI_PREAMBLE(env); + NAPI_CHECK_ARG(env, value); + NAPI_CHECK_ARG(env, result); + + auto jsValue = toJS(value); + // Despite documentation, Node.js's version of this function returns true for all kinds of + // TypedArray, not just Uint8Array + *result = jsValue.isCell() && isTypedArrayTypeIncludingDataView(jsValue.asCell()->type()); + NAPI_RETURN_SUCCESS(env); +} + +extern "C" napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) +{ + NAPI_PREAMBLE(env); + NAPI_CHECK_ARG(env, value); + NAPI_CHECK_ARG(env, result); + + auto jsValue = toJS(value); + *result = jsValue.isCell() && isTypedArrayType(jsValue.asCell()->type()); + NAPI_RETURN_SUCCESS(env); +} + // This is more efficient than using WTF::String::FromUTF8 // it doesn't copy the string // but it's only safe to use if we are not setting a property @@ -916,7 +940,7 @@ extern "C" napi_status napi_has_named_property(napi_env env, napi_value object, NAPI_CHECK_ARG(env, result); auto globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSObject* target = toJS(object).toObject(globalObject); NAPI_RETURN_IF_EXCEPTION(env); @@ -937,7 +961,7 @@ extern "C" napi_status napi_get_named_property(napi_env env, napi_value object, NAPI_CHECK_ARG(env, result); auto globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSObject* target = toJS(object).toObject(globalObject); NAPI_RETURN_IF_EXCEPTION(env); @@ -1017,7 +1041,7 @@ extern "C" size_t Bun__napi_module_register_count; extern "C" void napi_module_register(napi_module* mod) { auto* globalObject = defaultGlobalObject(); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto keyStr = WTF::String::fromUTF8(mod->nm_modname); globalObject->napiModuleRegisterCallCount++; Bun__napi_module_register_count++; @@ -1113,7 +1137,7 @@ extern "C" napi_status napi_wrap(napi_env env, NAPI_CHECK_ARG(env, js_object); auto* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue jsc_value = toJS(js_object); JSObject* jsc_object = jsc_value.getObject(); NAPI_RETURN_EARLY_IF_FALSE(env, jsc_object, napi_object_expected); @@ -1163,7 +1187,7 @@ extern "C" napi_status napi_remove_wrap(napi_env env, napi_value js_object, auto* napi_instance = jsDynamicCast(jsc_object); auto* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); NapiRef* ref = getWrapContentsIfExists(vm, globalObject, jsc_object); NAPI_RETURN_EARLY_IF_FALSE(env, ref, napi_invalid_arg); @@ -1197,7 +1221,7 @@ extern "C" napi_status napi_unwrap(napi_env env, napi_value js_object, NAPI_RETURN_EARLY_IF_FALSE(env, jsc_object, napi_object_expected); auto* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); NapiRef* ref = getWrapContentsIfExists(vm, globalObject, jsc_object); NAPI_RETURN_EARLY_IF_FALSE(env, ref, napi_invalid_arg); @@ -1217,7 +1241,7 @@ extern "C" napi_status napi_create_function(napi_env env, const char* utf8name, NAPI_CHECK_ARG(env, cb); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto name = WTF::String(); if (utf8name != nullptr) { @@ -1323,7 +1347,7 @@ napi_define_properties(napi_env env, napi_value object, size_t property_count, NAPI_RETURN_EARLY_IF_FALSE(env, properties || property_count == 0, napi_invalid_arg); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue objectValue = toJS(object); JSC::JSObject* objectObject = objectValue.getObject(); @@ -1354,7 +1378,7 @@ static JSC::ErrorInstance* createErrorWithCode(JSC::JSGlobalObject* globalObject // return the right error code ASSERT(!message.isNull()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); // we don't call JSC::createError() as it asserts the message is not an empty string "" auto* error = JSC::ErrorInstance::create(globalObject->vm(), globalObject->errorStructure(type), message, JSValue(), nullptr, RuntimeType::TypeNothing, type); @@ -1369,7 +1393,7 @@ static JSC::ErrorInstance* createErrorWithCode(JSC::JSGlobalObject* globalObject static napi_status throwErrorWithCStrings(napi_env env, const char* code_utf8, const char* msg_utf8, JSC::ErrorType type) { auto* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!msg_utf8) { @@ -1390,7 +1414,7 @@ static napi_status throwErrorWithCStrings(napi_env env, const char* code_utf8, c static napi_status createErrorWithNapiValues(napi_env env, napi_value code, napi_value message, JSC::ErrorType type, napi_value* result) { auto* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); RETURN_IF_EXCEPTION(scope, napi_pending_exception); @@ -1466,7 +1490,7 @@ extern "C" napi_status napi_add_finalizer(napi_env env, napi_value js_object, NAPI_CHECK_ARG(env, js_object); NAPI_CHECK_ARG(env, finalize_cb); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue objectValue = toJS(js_object); JSC::JSObject* object = objectValue.getObject(); @@ -1565,7 +1589,7 @@ extern "C" napi_status napi_detach_arraybuffer(napi_env env, { NAPI_PREAMBLE(env); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSArrayBuffer* jsArrayBuffer = JSC::jsDynamicCast(toJS(arraybuffer)); NAPI_RETURN_EARLY_IF_FALSE(env, jsArrayBuffer, napi_arraybuffer_expected); @@ -1645,7 +1669,7 @@ extern "C" napi_status napi_throw(napi_env env, napi_value error) { NAPI_PREAMBLE_NO_THROW_SCOPE(env); auto globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSC::JSValue value = toJS(error); @@ -1667,7 +1691,7 @@ extern "C" napi_status node_api_symbol_for(napi_env env, NAPI_CHECK_ARG(env, utf8description); auto* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto description = WTF::String::fromUTF8({ utf8description, length == NAPI_AUTO_LENGTH ? strlen(utf8description) : length }); *result = toNapi(JSC::Symbol::create(vm, vm.symbolRegistry().symbolForKey(description)), globalObject); @@ -1729,7 +1753,7 @@ extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value) NAPI_RETURN_EARLY_IF_FALSE(env, value.isObject(), napi_object_expected); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* object = JSC::jsCast(value); // TODO is this check necessary? @@ -1747,7 +1771,7 @@ extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value) NAPI_RETURN_EARLY_IF_FALSE(env, value.isObject(), napi_object_expected); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSObject* object = JSC::jsCast(value); // TODO is this check necessary? @@ -1831,7 +1855,7 @@ DEFINE_VISIT_CHILDREN(NapiClass); JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSObject* constructorTarget = asObject(callFrame->jsCallee()); JSObject* newTarget = asObject(callFrame->newTarget()); @@ -1967,7 +1991,7 @@ extern "C" napi_status napi_define_class(napi_env env, NAPI_RETURN_EARLY_IF_FALSE(env, properties || property_count == 0, napi_invalid_arg); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); size_t len = length; if (len == NAPI_AUTO_LENGTH) { len = strlen(utf8name); @@ -2054,7 +2078,7 @@ extern "C" napi_status napi_create_external_arraybuffer(napi_env env, void* exte NAPI_CHECK_ARG(env, result); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto arrayBuffer = ArrayBuffer::createFromBytes({ reinterpret_cast(external_data), byte_length }, createSharedTask([globalObject, finalize_hint, finalize_cb](void* p) { if (finalize_cb != nullptr) { @@ -2236,7 +2260,7 @@ extern "C" napi_status napi_create_object(napi_env env, napi_value* result) NAPI_CHECK_ARG(env, result); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSValue value = JSValue(NapiPrototype::create(vm, globalObject->NapiPrototypeStructure())); @@ -2255,7 +2279,7 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, NAPI_CHECK_ARG(env, result); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* structure = globalObject->NapiExternalStructure(); JSValue value = Bun::NapiExternal::create(vm, structure, data, finalize_hint, reinterpret_cast(finalize_cb)); @@ -2488,7 +2512,7 @@ extern "C" napi_status napi_run_script(napi_env env, napi_value script, Zig::GlobalObject* globalObject = toJS(env); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); WTF::String code = scriptValue.getString(globalObject); @@ -2577,7 +2601,7 @@ extern "C" napi_status napi_create_symbol(napi_env env, napi_value description, NAPI_CHECK_ARG(env, result); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::JSValue descriptionValue = toJS(description); if (descriptionValue && !descriptionValue.isUndefinedOrNull()) { @@ -2613,7 +2637,7 @@ extern "C" napi_status napi_new_instance(napi_env env, napi_value constructor, NAPI_RETURN_EARLY_IF_FALSE(env, constructData.type != JSC::CallData::Type::None, napi_function_expected); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer args; args.fill(vm, argc, [&](JSValue* buffer) { @@ -2638,7 +2662,7 @@ extern "C" napi_status napi_call_function(napi_env env, napi_value recv_napi, NAPI_RETURN_EARLY_IF_FALSE(env, callData.type != JSC::CallData::Type::None, napi_function_expected); Zig::GlobalObject* globalObject = toJS(env); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::MarkedArgumentBuffer args; args.fill(vm, argc, [&](JSValue* buffer) { @@ -2674,7 +2698,7 @@ extern "C" napi_status napi_type_tag_object(napi_env env, napi_value value, cons // cannot tag an object that is already tagged NAPI_RETURN_EARLY_IF_FALSE(env, existing_tag == nullptr, napi_invalid_arg); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* new_tag = Bun::NapiTypeTag::create(vm, globalObject->NapiTypeTagStructure(), *type_tag); globalObject->napiTypeTags()->set(vm, js_object, new_tag); NAPI_RETURN_SUCCESS(env); diff --git a/src/bun.js/bindings/napi_handle_scope.cpp b/src/bun.js/bindings/napi_handle_scope.cpp index ed3af6e6182bfe..6616125be04ab4 100644 --- a/src/bun.js/bindings/napi_handle_scope.cpp +++ b/src/bun.js/bindings/napi_handle_scope.cpp @@ -80,7 +80,7 @@ NapiHandleScopeImpl::Slot* NapiHandleScopeImpl::reserveSlot() NapiHandleScopeImpl* NapiHandleScope::open(Zig::GlobalObject* globalObject, bool escapable) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); // Do not create a new handle scope while a finalizer is in progress // This state is possible because we call napi finalizers immediately // so a finalizer can be called while an allocation is in progress. diff --git a/src/bun.js/bindings/shimmer.zig b/src/bun.js/bindings/shimmer.zig index 79c3dec3d4e630..4b306e2d015452 100644 --- a/src/bun.js/bindings/shimmer.zig +++ b/src/bun.js/bindings/shimmer.zig @@ -2,12 +2,10 @@ const std = @import("std"); const bun = @import("root").bun; const StaticExport = @import("./static_export.zig"); const Sizes = @import("./sizes.zig"); -pub const is_bindgen: bool = false; const headers = @import("./headers.zig"); fn isNullableType(comptime Type: type) bool { - return @typeInfo(Type) == .Optional or - (@typeInfo(Type) == .Pointer and @typeInfo(Type).Pointer.is_allowzero); + return @typeInfo(Type) == .optional or (@typeInfo(Type) == .pointer and @typeInfo(Type).pointer.is_allowzero); } const log = @import("../../output.zig").scoped(.CPP, true); @@ -18,7 +16,7 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp pub fn assertJSFunction(comptime funcs: anytype) void { inline for (funcs) |func| { - if (@typeInfo(@TypeOf(func)) != .Fn) { + if (@typeInfo(@TypeOf(func)) != .@"fn") { @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(func) ++ " to be a function but received " ++ @tagName(@typeInfo(@TypeOf(func)))); } } @@ -47,15 +45,15 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp // var ReturnTypeInfo: std.builtin.Type = @typeInfo(FromType); - // if (ReturnTypeInfo == .Pointer and NewReturnType != *anyopaque) { - // NewReturnType = ReturnTypeInfo.Pointer.child; + // if (ReturnTypeInfo == .pointer and NewReturnType != *anyopaque) { + // NewReturnType = ReturnTypeInfo.pointer.child; // ReturnTypeInfo = @typeInfo(NewReturnType); // } // switch (ReturnTypeInfo) { // .Union, // .Struct, - // .Enum, + // .@"enum", // => { // if (@hasDecl(ReturnTypeInfo., "Type")) { // return NewReturnType; @@ -95,8 +93,8 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp }; fn pointerChild(comptime Type: type) type { - if (@typeInfo(Type) == .Pointer) { - return @typeInfo(Type).Pointer.child_type; + if (@typeInfo(Type) == .pointer) { + return @typeInfo(Type).pointer.child_type; } return Type; @@ -116,17 +114,17 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp var functions: [std.meta.fieldNames(FunctionsType).len]StaticExport = undefined; for (std.meta.fieldNames(FunctionsType), 0..) |fn_name, i| { const Function = @TypeOf(@field(Functions, fn_name)); - if (@typeInfo(Function) != .Fn) { + if (@typeInfo(Function) != .@"fn") { @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to be a function but received " ++ @tagName(@typeInfo(Function))); } - const Fn: std.builtin.Type.Fn = @typeInfo(Function).Fn; + const Fn: std.builtin.Type.Fn = @typeInfo(Function).@"fn"; if (Function == bun.JSC.JSHostFunctionTypeWithCCallConvForAssertions and bun.JSC.conv != .C) { @compileError("Expected " ++ bun.meta.typeName(Function) ++ " to have a JSC.conv Calling Convention."); } else if (Function == bun.JSC.JSHostFunctionType) { // } else if (Function == bun.JSC.JSHostZigFunction) { // - } else if (Fn.calling_convention != .C) { + } else if (std.meta.activeTag(Fn.calling_convention) != std.meta.activeTag(std.builtin.CallingConvention.c)) { @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to have a C Calling Convention."); } @@ -151,10 +149,10 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp for (Functions) |thenable| { for ([_][]const u8{ "resolve", "reject" }) |fn_name| { const Function = @TypeOf(@field(thenable, fn_name)); - if (@typeInfo(Function) != .Fn) { + if (@typeInfo(Function) != .@"fn") { @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to be a function but received " ++ @tagName(@typeInfo(Function))); } - const Fn: std.builtin.Type.Fn = @typeInfo(Function).Fn; + const Fn: std.builtin.Type.@"fn" = @typeInfo(Function).@"fn"; if (Fn.calling_convention != .C) { @compileError("Expected " ++ @typeName(Parent) ++ "." ++ @typeName(Function) ++ " to have a C Calling Convention."); } @@ -177,7 +175,7 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp pub inline fn matchNullable(comptime ExpectedReturnType: type, comptime ExternReturnType: type, value: ExternReturnType) ExpectedReturnType { if (comptime isNullableType(ExpectedReturnType) != isNullableType(ExternReturnType)) { return value.?; - } else if (comptime (@typeInfo(ExpectedReturnType) == .Enum) and (@typeInfo(ExternReturnType) != .Enum)) { + } else if (comptime (@typeInfo(ExpectedReturnType) == .@"enum") and (@typeInfo(ExternReturnType) != .@"enum")) { return @as(ExpectedReturnType, @enumFromInt(value)); } else { return value; @@ -189,24 +187,22 @@ pub fn Shimmer(comptime _namespace: []const u8, comptime _name: []const u8, comp if (!@hasDecl(Parent, typeName)) { @compileError(@typeName(Parent) ++ " is missing cppFn: " ++ typeName); } - break :ret @typeInfo(@TypeOf(@field(Parent, typeName))).Fn.return_type.?; + break :ret @typeInfo(@TypeOf(@field(Parent, typeName))).@"fn".return_type.?; }) { log(comptime name ++ "__" ++ typeName, .{}); @setEvalBranchQuota(99999); - if (comptime is_bindgen) { - unreachable; - } else { + { const Fn = comptime @field(headers, symbolName(typeName)); - if (@typeInfo(@TypeOf(Fn)).Fn.params.len > 0) + if (@typeInfo(@TypeOf(Fn)).@"fn".params.len > 0) return matchNullable( - comptime @typeInfo(@TypeOf(@field(Parent, typeName))).Fn.return_type.?, - comptime @typeInfo(@TypeOf(Fn)).Fn.return_type.?, + comptime @typeInfo(@TypeOf(@field(Parent, typeName))).@"fn".return_type.?, + comptime @typeInfo(@TypeOf(Fn)).@"fn".return_type.?, @call(.auto, Fn, args), ); return matchNullable( - comptime @typeInfo(@TypeOf(@field(Parent, typeName))).Fn.return_type.?, - comptime @typeInfo(@TypeOf(Fn)).Fn.return_type.?, + comptime @typeInfo(@TypeOf(@field(Parent, typeName))).@"fn".return_type.?, + comptime @typeInfo(@TypeOf(Fn)).@"fn".return_type.?, Fn(), ); } diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index fd4d1ce63cded2..7f70a1022da55e 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -300,7 +300,7 @@ JSC_DECLARE_CUSTOM_SETTER(jsSqlStatementSetSafeIntegers); static JSValue createSQLiteError(JSC::JSGlobalObject* globalObject, sqlite3* db) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); int code = sqlite3_extended_errcode(db); int byteOffset = sqlite3_error_offset(db); @@ -610,7 +610,7 @@ static void initializeColumnNames(JSC::JSGlobalObject* lexicalGlobalObject, JSSQ castedThis->validColumns.clearAll(); castedThis->update_version(); - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* stmt = castedThis->stmt; @@ -831,7 +831,7 @@ static JSC::JSValue rebindObject(JSC::JSGlobalObject* globalObject, SQLiteBindin { int count = 0; - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto& structure = *target->structure(); bindings.ensureNamesLoaded(vm, stmt); const auto& bindingNames = bindings.bindingNames; @@ -1029,7 +1029,7 @@ static JSC::JSValue rebindStatement(JSC::JSGlobalObject* lexicalGlobalObject, JS JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSetCustomSQLite, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1073,7 +1073,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSetCustomSQLite, (JSC::JSGlobalObject * l JSC_DEFINE_HOST_FUNCTION(jsSQLStatementDeserialize, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1165,7 +1165,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementDeserialize, (JSC::JSGlobalObject * lexic JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSerialize, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1206,7 +1206,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSerialize, (JSC::JSGlobalObject * lexical JSC_DEFINE_HOST_FUNCTION(jsSQLStatementLoadExtensionFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1266,7 +1266,7 @@ static bool isSkippedInSQLiteQuery(const char c) // does not return anything JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1422,7 +1422,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteFunction, (JSC::JSGlobalObject * l JSC_DEFINE_HOST_FUNCTION(jsSQLStatementIsInTransactionFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1458,7 +1458,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementIsInTransactionFunction, (JSC::JSGlobalOb JSC_DEFINE_HOST_FUNCTION(jsSQLStatementPrepareStatementFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1559,7 +1559,7 @@ JSSQLStatementConstructor* JSSQLStatementConstructor::create(JSC::VM& vm, JSC::J JSC_DEFINE_HOST_FUNCTION(jsSQLStatementOpenStatementFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1639,7 +1639,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementOpenStatementFunction, (JSC::JSGlobalObje JSC_DEFINE_HOST_FUNCTION(jsSQLStatementCloseStatementFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1690,7 +1690,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementCloseStatementFunction, (JSC::JSGlobalObj JSC_DEFINE_HOST_FUNCTION(jsSQLStatementFcntlFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = callFrame->thisValue(); @@ -1810,7 +1810,7 @@ static inline JSC::JSValue constructResultObject(JSC::JSGlobalObject* lexicalGlo { auto& columnNames = castedThis->columnNames->data()->propertyNameVector(); int count = columnNames.size(); - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); // 64 is the maximum we can preallocate here // see https://github.com/oven-sh/bun/issues/987 @@ -1892,7 +1892,7 @@ static inline JSC::JSArray* constructResultRow(JSC::VM& vm, JSC::JSGlobalObject* JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSetPrototypeFunction, (JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->thisValue()); @@ -1953,7 +1953,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementSetPrototypeFunction, (JSGlobalObject * l JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionIterate, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto castedThis = jsDynamicCast(callFrame->thisValue()); @@ -2004,7 +2004,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionIterate, (JSC::JS JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto castedThis = jsDynamicCast(callFrame->thisValue()); @@ -2084,7 +2084,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlob JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionGet, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto castedThis = jsDynamicCast(callFrame->thisValue()); @@ -2136,7 +2136,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionGet, (JSC::JSGlob JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRows, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto castedThis = jsDynamicCast(callFrame->thisValue()); @@ -2215,7 +2215,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRows, (JSC::JSGlo JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRun, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto castedThis = jsDynamicCast(callFrame->thisValue()); @@ -2280,7 +2280,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRun, (JSC::JSGlob JSC_DEFINE_HOST_FUNCTION(jsSQLStatementToStringFunction, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(callFrame->thisValue()); auto scope = DECLARE_THROW_SCOPE(vm); @@ -2299,7 +2299,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementToStringFunction, (JSC::JSGlobalObject * JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnNames, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(JSValue::decode(thisValue)); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_THIS @@ -2327,7 +2327,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnNames, (JSGlobalObject * lexical JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnCount, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(JSValue::decode(thisValue)); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_THIS @@ -2338,7 +2338,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnCount, (JSGlobalObject * lexical JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetParamCount, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(JSValue::decode(thisValue)); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_THIS @@ -2349,7 +2349,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetParamCount, (JSGlobalObject * lexicalG JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetSafeIntegers, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName attributeName)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(JSValue::decode(thisValue)); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_THIS @@ -2360,7 +2360,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetSafeIntegers, (JSGlobalObject * lexica JSC_DEFINE_CUSTOM_SETTER(jsSqlStatementSetSafeIntegers, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, PropertyName attributeName)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(JSValue::decode(thisValue)); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_THIS @@ -2374,7 +2374,7 @@ JSC_DEFINE_CUSTOM_SETTER(jsSqlStatementSetSafeIntegers, (JSGlobalObject * lexica JSC_DEFINE_HOST_FUNCTION(jsSQLStatementFunctionFinalize, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSSQLStatement* castedThis = jsDynamicCast(callFrame->thisValue()); auto scope = DECLARE_THROW_SCOPE(vm); CHECK_THIS @@ -2426,7 +2426,7 @@ void JSSQLStatement::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) JSC::JSValue JSSQLStatement::rebind(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSValue values, bool clone, sqlite3* db) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* stmt = this->stmt; diff --git a/src/bun.js/bindings/v8/V8External.cpp b/src/bun.js/bindings/v8/V8External.cpp index 51023c986356d4..7697289a5c1b4e 100644 --- a/src/bun.js/bindings/v8/V8External.cpp +++ b/src/bun.js/bindings/v8/V8External.cpp @@ -10,7 +10,7 @@ namespace v8 { Local External::New(Isolate* isolate, void* value) { auto globalObject = isolate->globalObject(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto structure = globalObject->NapiExternalStructure(); Bun::NapiExternal* val = Bun::NapiExternal::create(vm, structure, value, nullptr, nullptr); return isolate->currentHandleScope()->createLocal(vm, val); diff --git a/src/bun.js/bindings/v8/V8FunctionTemplate.cpp b/src/bun.js/bindings/v8/V8FunctionTemplate.cpp index 36fdf022a17d0e..cbdc754292c7ec 100644 --- a/src/bun.js/bindings/v8/V8FunctionTemplate.cpp +++ b/src/bun.js/bindings/v8/V8FunctionTemplate.cpp @@ -52,7 +52,7 @@ Local FunctionTemplate::New( "Passing allowed_receiver_instance_type_range_end to FunctionTemplate::New is not yet supported"); auto globalObject = isolate->globalObject(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* globalInternals = globalObject->V8GlobalInternals(); JSValue jsc_data = data.IsEmpty() ? JSC::jsUndefined() : data->localToJSValue(); diff --git a/src/bun.js/bindings/v8/V8Object.cpp b/src/bun.js/bindings/v8/V8Object.cpp index e69031ec2de14c..f6f0bdc0961bc3 100644 --- a/src/bun.js/bindings/v8/V8Object.cpp +++ b/src/bun.js/bindings/v8/V8Object.cpp @@ -43,7 +43,7 @@ Maybe Object::Set(Local context, Local key, Local v JSObject* object = localToObjectPointer(); JSValue k = key->localToJSValue(); JSValue v = value->localToJSValue(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); PutPropertySlot slot(object, false); diff --git a/src/bun.js/bindings/v8/V8ObjectTemplate.cpp b/src/bun.js/bindings/v8/V8ObjectTemplate.cpp index 3eb5b5c7a5aa29..bf5c16b7f8be04 100644 --- a/src/bun.js/bindings/v8/V8ObjectTemplate.cpp +++ b/src/bun.js/bindings/v8/V8ObjectTemplate.cpp @@ -12,7 +12,7 @@ Local ObjectTemplate::New(Isolate* isolate, LocalglobalObject(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* globalInternals = globalObject->V8GlobalInternals(); auto* structure = globalInternals->objectTemplateStructure(globalObject); // TODO pass constructor diff --git a/src/bun.js/bindings/v8/node.cpp b/src/bun.js/bindings/v8/node.cpp index 527bc8addf141c..d00402ab5be9d7 100644 --- a/src/bun.js/bindings/v8/node.cpp +++ b/src/bun.js/bindings/v8/node.cpp @@ -40,7 +40,7 @@ void node_module_register(void* opaque_mod) { // TODO unify this with napi_module_register auto* globalObject = defaultGlobalObject(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* mod = reinterpret_cast(opaque_mod); auto keyStr = WTF::String::fromUTF8(mod->nm_modname); diff --git a/src/bun.js/bindings/v8/shim/FunctionTemplate.cpp b/src/bun.js/bindings/v8/shim/FunctionTemplate.cpp index db04da9fc27aa6..aeba5542fc2d83 100644 --- a/src/bun.js/bindings/v8/shim/FunctionTemplate.cpp +++ b/src/bun.js/bindings/v8/shim/FunctionTemplate.cpp @@ -60,7 +60,7 @@ JSC::EncodedJSValue FunctionTemplate::functionCall(JSC::JSGlobalObject* globalOb auto* callee = JSC::jsDynamicCast(callFrame->jsCallee()); auto* functionTemplate = callee->functionTemplate(); auto* isolate = JSC::jsCast(globalObject)->V8GlobalInternals()->isolate(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); WTF::Vector args(callFrame->argumentCount() + 1); diff --git a/src/bun.js/bindings/webcore/AbortSignal.cpp b/src/bun.js/bindings/webcore/AbortSignal.cpp index 7d22ef7a9b822c..e37bd9f7ff1712 100644 --- a/src/bun.js/bindings/webcore/AbortSignal.cpp +++ b/src/bun.js/bindings/webcore/AbortSignal.cpp @@ -66,7 +66,7 @@ Ref AbortSignal::timeout(ScriptExecutionContext& context, uint64_t signal->setHasActiveTimeoutTimer(true); auto action = [signal](ScriptExecutionContext& context) mutable { auto* globalObject = defaultGlobalObject(context.globalObject()); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); Locker locker { vm.apiLock() }; signal->signalAbort(toJS(globalObject, globalObject, DOMException::create(TimeoutError))); signal->setHasActiveTimeoutTimer(false); @@ -195,6 +195,7 @@ void AbortSignal::cleanNativeBindings(void* ref) }); std::exchange(m_native_callbacks, WTFMove(callbacks)); + this->eventListenersDidChange(); } // https://dom.spec.whatwg.org/#abortsignal-follow @@ -218,7 +219,7 @@ void AbortSignal::signalFollow(AbortSignal& signal) void AbortSignal::eventListenersDidChange() { - m_hasAbortEventListener = hasEventListeners(eventNames().abortEvent); + m_hasAbortEventListener = hasEventListeners(eventNames().abortEvent) or !m_native_callbacks.isEmpty(); } uint32_t AbortSignal::addAbortAlgorithmToSignal(AbortSignal& signal, Ref&& algorithm) diff --git a/src/bun.js/bindings/webcore/BroadcastChannel.cpp b/src/bun.js/bindings/webcore/BroadcastChannel.cpp index d52911bb789e59..61c07cf5f93b8e 100644 --- a/src/bun.js/bindings/webcore/BroadcastChannel.cpp +++ b/src/bun.js/bindings/webcore/BroadcastChannel.cpp @@ -264,7 +264,7 @@ void BroadcastChannel::dispatchMessage(Ref&& message) if (!globalObject) return; - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); Vector> dummyPorts; auto event = MessageEvent::create(*globalObject, WTFMove(message), {}, {}, std::nullopt, WTFMove(dummyPorts)); diff --git a/src/bun.js/bindings/webcore/ContextDestructionObserver.h b/src/bun.js/bindings/webcore/ContextDestructionObserver.h index f206ad80354e16..c90a25bd0adc98 100644 --- a/src/bun.js/bindings/webcore/ContextDestructionObserver.h +++ b/src/bun.js/bindings/webcore/ContextDestructionObserver.h @@ -3,11 +3,10 @@ #pragma once #include "root.h" +#include "ScriptExecutionContext.h" namespace WebCore { -class ScriptExecutionContext; - class ContextDestructionObserver { public: diff --git a/src/bun.js/bindings/webcore/JSAbortController.cpp b/src/bun.js/bindings/webcore/JSAbortController.cpp index 467a6ce82977f9..81a279ff6e5f20 100644 --- a/src/bun.js/bindings/webcore/JSAbortController.cpp +++ b/src/bun.js/bindings/webcore/JSAbortController.cpp @@ -98,7 +98,7 @@ using JSAbortControllerDOMConstructor = JSDOMConstructor; template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSAbortControllerDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); diff --git a/src/bun.js/bindings/webcore/JSAbortController.h b/src/bun.js/bindings/webcore/JSAbortController.h index 4d8d8c2fa17099..483328aa88d16a 100644 --- a/src/bun.js/bindings/webcore/JSAbortController.h +++ b/src/bun.js/bindings/webcore/JSAbortController.h @@ -31,7 +31,7 @@ class JSAbortController : public JSDOMWrapper { using Base = JSDOMWrapper; static JSAbortController* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref&& impl) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSAbortController* ptr = new (NotNull, JSC::allocateCell(vm)) JSAbortController(structure, *globalObject, WTFMove(impl)); ptr->finishCreation(vm); return ptr; diff --git a/src/bun.js/bindings/webcore/JSAbortSignal.h b/src/bun.js/bindings/webcore/JSAbortSignal.h index 5b0600a22f9ec1..4de1f1b746e166 100644 --- a/src/bun.js/bindings/webcore/JSAbortSignal.h +++ b/src/bun.js/bindings/webcore/JSAbortSignal.h @@ -33,7 +33,7 @@ class JSAbortSignal : public JSEventTarget { using DOMWrapped = AbortSignal; static JSAbortSignal* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref&& impl) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSAbortSignal* ptr = new (NotNull, JSC::allocateCell(vm)) JSAbortSignal(structure, *globalObject, WTFMove(impl)); ptr->finishCreation(vm); return ptr; diff --git a/src/bun.js/bindings/webcore/JSAddEventListenerOptions.cpp b/src/bun.js/bindings/webcore/JSAddEventListenerOptions.cpp index 6ef60b2a3d25e7..bda4e35f991e48 100644 --- a/src/bun.js/bindings/webcore/JSAddEventListenerOptions.cpp +++ b/src/bun.js/bindings/webcore/JSAddEventListenerOptions.cpp @@ -31,7 +31,7 @@ using namespace JSC; template<> AddEventListenerOptions convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp index 93b2a40656a2d3..ecf1790f5118a8 100644 --- a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp +++ b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp @@ -104,7 +104,7 @@ using JSBroadcastChannelDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBroadcastChannelDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -195,7 +195,7 @@ JSValue JSBroadcastChannel::getConstructor(VM& vm, const JSGlobalObject* globalO JSC_DEFINE_CUSTOM_GETTER(jsBroadcastChannelConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSByteLengthQueuingStrategy.cpp b/src/bun.js/bindings/webcore/JSByteLengthQueuingStrategy.cpp index 523734aab47d39..1703532701892f 100644 --- a/src/bun.js/bindings/webcore/JSByteLengthQueuingStrategy.cpp +++ b/src/bun.js/bindings/webcore/JSByteLengthQueuingStrategy.cpp @@ -159,7 +159,7 @@ void JSByteLengthQueuingStrategy::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsByteLengthQueuingStrategyConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSCloseEvent.cpp b/src/bun.js/bindings/webcore/JSCloseEvent.cpp index 9d11dbad9868ee..18883e2e346919 100644 --- a/src/bun.js/bindings/webcore/JSCloseEvent.cpp +++ b/src/bun.js/bindings/webcore/JSCloseEvent.cpp @@ -50,7 +50,7 @@ using namespace JSC; template<> CloseEvent::Init convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); @@ -177,7 +177,7 @@ using JSCloseEventDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSCloseEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -268,7 +268,7 @@ JSValue JSCloseEvent::getConstructor(VM& vm, const JSGlobalObject* globalObject) JSC_DEFINE_CUSTOM_GETTER(jsCloseEventConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSCountQueuingStrategy.cpp b/src/bun.js/bindings/webcore/JSCountQueuingStrategy.cpp index 5d83696115a574..6fcd6817c9e410 100644 --- a/src/bun.js/bindings/webcore/JSCountQueuingStrategy.cpp +++ b/src/bun.js/bindings/webcore/JSCountQueuingStrategy.cpp @@ -159,7 +159,7 @@ void JSCountQueuingStrategy::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsCountQueuingStrategyConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSCustomEvent.cpp b/src/bun.js/bindings/webcore/JSCustomEvent.cpp index fef4d409a8d20b..d96394d3a3d67e 100644 --- a/src/bun.js/bindings/webcore/JSCustomEvent.cpp +++ b/src/bun.js/bindings/webcore/JSCustomEvent.cpp @@ -54,7 +54,7 @@ using namespace JSC; template<> CustomEvent::Init convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); @@ -160,7 +160,7 @@ using JSCustomEventDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSCustomEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -250,7 +250,7 @@ JSValue JSCustomEvent::getConstructor(VM& vm, const JSGlobalObject* globalObject JSC_DEFINE_CUSTOM_GETTER(jsCustomEventConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSDOMBuiltinConstructor.h b/src/bun.js/bindings/webcore/JSDOMBuiltinConstructor.h index afd728ec6c1abb..4e6200fb1e54d9 100644 --- a/src/bun.js/bindings/webcore/JSDOMBuiltinConstructor.h +++ b/src/bun.js/bindings/webcore/JSDOMBuiltinConstructor.h @@ -94,7 +94,7 @@ template inline JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES J { ASSERT(callFrame); auto* castedThis = JSC::jsCast(callFrame->jsCallee()); - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->thisValue() != castedThis) { throwTypeError(lexicalGlobalObject, scope, "Constructor called as a function"_s); diff --git a/src/bun.js/bindings/webcore/JSDOMConvertCallbacks.h b/src/bun.js/bindings/webcore/JSDOMConvertCallbacks.h index 05dcc37ae1a513..b3ab6a1e086d20 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertCallbacks.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertCallbacks.h @@ -38,7 +38,7 @@ template struct Converter> : DefaultConverter template static RefPtr convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!value.isCallable()) { @@ -52,7 +52,7 @@ template struct Converter> : DefaultConverter template static RefPtr convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!value.isCallable()) { @@ -85,7 +85,7 @@ template struct Converter> : DefaultConverte template static RefPtr convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!value.isObject()) { diff --git a/src/bun.js/bindings/webcore/JSDOMConvertNumbers.h b/src/bun.js/bindings/webcore/JSDOMConvertNumbers.h index 9d8bd929eeb4a7..0daac2583a7ec8 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertNumbers.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertNumbers.h @@ -286,7 +286,7 @@ template<> struct Converter : DefaultConverter { static float convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); double number = value.toNumber(&lexicalGlobalObject); RETURN_IF_EXCEPTION(scope, 0.0); @@ -318,7 +318,7 @@ template<> struct Converter : DefaultConverter struct Converter : DefaultConverter { static double convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); double number = value.toNumber(&lexicalGlobalObject); RETURN_IF_EXCEPTION(scope, 0.0); diff --git a/src/bun.js/bindings/webcore/JSDOMConvertObject.h b/src/bun.js/bindings/webcore/JSDOMConvertObject.h index 2acdad0d6c4163..fd42c5f9811d88 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertObject.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertObject.h @@ -38,7 +38,7 @@ template<> struct Converter : DefaultConverter { template static JSC::Strong convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!value.isObject()) { diff --git a/src/bun.js/bindings/webcore/JSDOMConvertPromise.h b/src/bun.js/bindings/webcore/JSDOMConvertPromise.h index 5d307c86f62b6d..c3ca6bb158d80f 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertPromise.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertPromise.h @@ -39,7 +39,7 @@ template struct Converter> : DefaultConverter static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto* globalObject = JSC::jsDynamicCast(&lexicalGlobalObject); if (!globalObject) diff --git a/src/bun.js/bindings/webcore/JSDOMConvertScheduledAction.h b/src/bun.js/bindings/webcore/JSDOMConvertScheduledAction.h index 72fb8450dfcaf3..61ac02caff985f 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertScheduledAction.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertScheduledAction.h @@ -35,7 +35,7 @@ namespace WebCore { template<> struct Converter : DefaultConverter { static std::unique_ptr convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, JSDOMGlobalObject& globalObject) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!value.isCallable()) { diff --git a/src/bun.js/bindings/webcore/JSDOMConvertSequences.h b/src/bun.js/bindings/webcore/JSDOMConvertSequences.h index 9ac0e4281e68f9..3eada58623174f 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertSequences.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertSequences.h @@ -378,7 +378,7 @@ template struct JSConverter> { template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const Vector& vector) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::MarkedArgumentBuffer list; list.ensureCapacity(vector.size()); @@ -416,7 +416,7 @@ template struct JSConverter> { template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const Vector& vector) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::MarkedArgumentBuffer list; list.ensureCapacity(vector.size()); diff --git a/src/bun.js/bindings/webcore/JSDOMConvertUnion.h b/src/bun.js/bindings/webcore/JSDOMConvertUnion.h index 2d4c5e5f9508cf..837a9be2928942 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertUnion.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertUnion.h @@ -165,7 +165,7 @@ template struct Converter> : DefaultConverter struct Converter> : DefaultConverter static RefPtr convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (!value.isObject()) { exceptionThrower(lexicalGlobalObject, scope); diff --git a/src/bun.js/bindings/webcore/JSDOMException.cpp b/src/bun.js/bindings/webcore/JSDOMException.cpp index 4a1650a25dce5e..dd6c85e82630f8 100644 --- a/src/bun.js/bindings/webcore/JSDOMException.cpp +++ b/src/bun.js/bindings/webcore/JSDOMException.cpp @@ -122,7 +122,7 @@ static const HashTableValue JSDOMExceptionConstructorTableValues[] = { template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMExceptionDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -244,7 +244,7 @@ void JSDOMException::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsDOMExceptionConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.cpp b/src/bun.js/bindings/webcore/JSDOMFormData.cpp index 1ddee5427b7c70..94c7a45cde7d23 100644 --- a/src/bun.js/bindings/webcore/JSDOMFormData.cpp +++ b/src/bun.js/bindings/webcore/JSDOMFormData.cpp @@ -110,7 +110,7 @@ static JSC_DECLARE_CUSTOM_GETTER(jsDOMFormDataConstructor); JSC_DEFINE_CUSTOM_GETTER(jsDOMFormDataPrototype_getLength, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto* thisObject = jsDynamicCast(JSValue::decode(thisValue)); auto throwScope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(!thisObject)) @@ -156,7 +156,7 @@ using JSDOMFormDataDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMFormDataDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -264,7 +264,7 @@ void JSDOMFormData::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsDOMFormDataConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSDOMIterator.cpp b/src/bun.js/bindings/webcore/JSDOMIterator.cpp index 4dc57d5e653aa1..7f522208ace14a 100644 --- a/src/bun.js/bindings/webcore/JSDOMIterator.cpp +++ b/src/bun.js/bindings/webcore/JSDOMIterator.cpp @@ -38,7 +38,7 @@ void addValueIterableMethods(JSC::JSGlobalObject& globalObject, JSC::JSObject& p JSC::JSGlobalObject* lexicalGlobalObject = &globalObject; ASSERT(lexicalGlobalObject); - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto copyProperty = [&](const JSC::Identifier& arrayIdentifier, const JSC::Identifier& otherIdentifier, unsigned attributes = 0) { JSC::JSValue value = arrayPrototype->getDirect(vm, arrayIdentifier); diff --git a/src/bun.js/bindings/webcore/JSDOMIterator.h b/src/bun.js/bindings/webcore/JSDOMIterator.h index cb3becd31303e9..f9d145acec853a 100644 --- a/src/bun.js/bindings/webcore/JSDOMIterator.h +++ b/src/bun.js/bindings/webcore/JSDOMIterator.h @@ -258,7 +258,7 @@ JSC::JSValue JSDOMIteratorBase::next(JSC::JSGlobalObj template JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMIteratorPrototype::next(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto iterator = JSC::jsDynamicCast*>(callFrame->thisValue()); diff --git a/src/bun.js/bindings/webcore/JSDOMOperation.cpp b/src/bun.js/bindings/webcore/JSDOMOperation.cpp index 4aa4a8b6267b78..a102ff1d685a7e 100644 --- a/src/bun.js/bindings/webcore/JSDOMOperation.cpp +++ b/src/bun.js/bindings/webcore/JSDOMOperation.cpp @@ -12,7 +12,7 @@ JSC::JSObject* createNotEnoughArgumentsErrorBun(JSC::JSGlobalObject* globalObjec { JSC::JSObject* error = JSC::createNotEnoughArgumentsError(globalObject); if (LIKELY(error)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); const auto& names = WebCore::builtinNames(vm); error->putDirect(vm, names.codePublicName(), JSC::jsString(vm, WTF::String("ERR_MISSING_ARGS"_s)), 0); } diff --git a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h index 70160867790e82..a0256aa3adec29 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h +++ b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.h @@ -47,7 +47,7 @@ class DeferredPromise : public DOMGuarded { static RefPtr create(JSDOMGlobalObject& globalObject, Mode mode = Mode::ClearPromiseOnResolve) { - JSC::VM& vm = JSC::getVM(&globalObject); + auto& vm = JSC::getVM(&globalObject); auto* promise = JSC::JSPromise::create(vm, globalObject.promiseStructure()); ASSERT(promise); return adoptRef(new DeferredPromise(globalObject, *promise, mode)); @@ -150,7 +150,7 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); auto* lexicalGlobalObject = globalObject(); - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSC::JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); resolve(*lexicalGlobalObject, callback(*globalObject())); @@ -167,7 +167,7 @@ class DeferredPromise : public DOMGuarded { ASSERT(deferred()); ASSERT(globalObject()); auto* lexicalGlobalObject = globalObject(); - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSC::JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); reject(*lexicalGlobalObject, callback(*globalObject()), rejectAsHandled); @@ -326,7 +326,7 @@ using PromiseFunction = void(JSC::JSGlobalObject&, JSC::CallFrame&, Ref inline JSC::JSValue callPromiseFunction(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame& callFrame) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto catchScope = DECLARE_CATCH_SCOPE(vm); auto& globalObject = *JSC::jsSecureCast(&lexicalGlobalObject); @@ -345,7 +345,7 @@ inline JSC::JSValue callPromiseFunction(JSC::JSGlobalObject& lexicalGlobalObject template inline JSC::JSValue callPromiseFunction(JSC::JSGlobalObject& lexicalGlobalObject, JSC::CallFrame& callFrame, PromiseFunctor functor) { - JSC::VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto catchScope = DECLARE_CATCH_SCOPE(vm); auto& globalObject = *JSC::jsSecureCast(&lexicalGlobalObject); diff --git a/src/bun.js/bindings/webcore/JSDOMURL.cpp b/src/bun.js/bindings/webcore/JSDOMURL.cpp index c190da7c098828..444393f4970506 100755 --- a/src/bun.js/bindings/webcore/JSDOMURL.cpp +++ b/src/bun.js/bindings/webcore/JSDOMURL.cpp @@ -150,7 +150,7 @@ size_t JSDOMURL::estimatedSize(JSC::JSCell* cell, JSC::VM& vm) template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMURLDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -171,6 +171,8 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMURLDOMConstructor::const RETURN_IF_EXCEPTION(throwScope, {}); setSubclassStructureIfNeeded(lexicalGlobalObject, callFrame, asObject(jsValue)); RETURN_IF_EXCEPTION(throwScope, {}); + auto* jsDOMURL = jsCast(jsValue.asCell()); + vm.heap.reportExtraMemoryAllocated(jsDOMURL, jsDOMURL->wrapped().memoryCostForGC()); return JSValue::encode(jsValue); } JSC_ANNOTATE_HOST_FUNCTION(JSDOMURLDOMConstructorConstruct, JSDOMURLDOMConstructor::construct); @@ -787,6 +789,7 @@ void JSDOMURL::visitChildrenImpl(JSCell* cell, Visitor& visitor) ASSERT_GC_OBJECT_INHERITS(thisObject, info()); Base::visitChildren(thisObject, visitor); visitor.append(thisObject->m_searchParams); + visitor.reportExtraMemoryVisited(thisObject->protectedWrapped()->memoryCostForGC()); } DEFINE_VISIT_CHILDREN(JSDOMURL); diff --git a/src/bun.js/bindings/webcore/JSErrorEvent.cpp b/src/bun.js/bindings/webcore/JSErrorEvent.cpp index 109fb8cc59b859..45039d780ff69e 100644 --- a/src/bun.js/bindings/webcore/JSErrorEvent.cpp +++ b/src/bun.js/bindings/webcore/JSErrorEvent.cpp @@ -53,7 +53,7 @@ using namespace JSC; template<> ErrorEvent::Init convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); @@ -206,7 +206,7 @@ using JSErrorEventDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSErrorEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -299,7 +299,7 @@ JSValue JSErrorEvent::getConstructor(VM& vm, const JSGlobalObject* globalObject) JSC_DEFINE_CUSTOM_GETTER(jsErrorEventConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSEvent.cpp b/src/bun.js/bindings/webcore/JSEvent.cpp index 0fe7c06d5d640f..cbb6e652c0d49e 100644 --- a/src/bun.js/bindings/webcore/JSEvent.cpp +++ b/src/bun.js/bindings/webcore/JSEvent.cpp @@ -148,7 +148,7 @@ static_assert(Event::BUBBLING_PHASE == 3, "BUBBLING_PHASE in Event does not matc template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -278,7 +278,7 @@ void JSEvent::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsEventConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSEventEmitter.cpp b/src/bun.js/bindings/webcore/JSEventEmitter.cpp index d091d8959c8c4f..c1507485378bc5 100644 --- a/src/bun.js/bindings/webcore/JSEventEmitter.cpp +++ b/src/bun.js/bindings/webcore/JSEventEmitter.cpp @@ -99,7 +99,7 @@ using JSEventEmitterDOMConstructor = JSDOMConstructorCallable; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventEmitterDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -127,7 +127,7 @@ JSC_ANNOTATE_HOST_FUNCTION(JSEventEmitterDOMConstructorConstruct, JSEventEmitter template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventEmitterDOMConstructor::call(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -247,7 +247,7 @@ void JSEventEmitter::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsEventEmitterConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSEventInit.cpp b/src/bun.js/bindings/webcore/JSEventInit.cpp index 5ec28613e951e0..ea979f1d3585ef 100644 --- a/src/bun.js/bindings/webcore/JSEventInit.cpp +++ b/src/bun.js/bindings/webcore/JSEventInit.cpp @@ -29,7 +29,7 @@ using namespace JSC; template<> EventInit convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSEventListenerOptions.cpp b/src/bun.js/bindings/webcore/JSEventListenerOptions.cpp index a1e6fb69f6ea38..b4034dbd81608e 100644 --- a/src/bun.js/bindings/webcore/JSEventListenerOptions.cpp +++ b/src/bun.js/bindings/webcore/JSEventListenerOptions.cpp @@ -29,7 +29,7 @@ using namespace JSC; template<> EventListenerOptions convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSEventModifierInit.cpp b/src/bun.js/bindings/webcore/JSEventModifierInit.cpp index 0e9d2c80429322..d5ec4ea6964793 100644 --- a/src/bun.js/bindings/webcore/JSEventModifierInit.cpp +++ b/src/bun.js/bindings/webcore/JSEventModifierInit.cpp @@ -33,7 +33,7 @@ using namespace JSC; template<> EventModifierInit convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSEventTarget.cpp b/src/bun.js/bindings/webcore/JSEventTarget.cpp index 4db90950e57344..5ed25ce295754f 100644 --- a/src/bun.js/bindings/webcore/JSEventTarget.cpp +++ b/src/bun.js/bindings/webcore/JSEventTarget.cpp @@ -102,7 +102,7 @@ using JSEventTargetDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventTargetDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -197,7 +197,7 @@ void JSEventTarget::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsEventTargetConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) @@ -348,7 +348,7 @@ void JSEventTargetOwner::finalize(JSC::Handle handle, void* contex JSC_DEFINE_HOST_FUNCTION(jsEventTargetGetEventListenersCount, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* thisValue = jsDynamicCast(callFrame->argument(0)); if (!thisValue) return JSC::JSValue::encode(JSC::jsUndefined()); diff --git a/src/bun.js/bindings/webcore/JSEventTargetNode.cpp b/src/bun.js/bindings/webcore/JSEventTargetNode.cpp index 314b64d55ef1c4..fc6b5b8065511c 100644 --- a/src/bun.js/bindings/webcore/JSEventTargetNode.cpp +++ b/src/bun.js/bindings/webcore/JSEventTargetNode.cpp @@ -16,7 +16,7 @@ using namespace JSC; using namespace WebCore; JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeEventsGetEventListeners, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 2) { diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp index c2d42fc86de4ba..663388a19bd150 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp @@ -125,7 +125,7 @@ size_t JSFetchHeaders::estimatedSize(JSC::JSCell* cell, JSC::VM& vm) template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSFetchHeadersDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -377,7 +377,7 @@ void JSFetchHeaders::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsFetchHeadersConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSMessageChannel.cpp b/src/bun.js/bindings/webcore/JSMessageChannel.cpp index a5c8ff719702a5..f4852c397cb8d3 100644 --- a/src/bun.js/bindings/webcore/JSMessageChannel.cpp +++ b/src/bun.js/bindings/webcore/JSMessageChannel.cpp @@ -91,7 +91,7 @@ using JSMessageChannelDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSMessageChannelDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -179,7 +179,7 @@ void JSMessageChannel::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsMessageChannelConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSMessageEvent.cpp b/src/bun.js/bindings/webcore/JSMessageEvent.cpp index 469afee0f21ef1..9186e193e939c3 100644 --- a/src/bun.js/bindings/webcore/JSMessageEvent.cpp +++ b/src/bun.js/bindings/webcore/JSMessageEvent.cpp @@ -62,7 +62,7 @@ using namespace JSC; template<> MessageEvent::Init convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); @@ -219,7 +219,7 @@ using JSMessageEventDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSMessageEventDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -315,7 +315,7 @@ JSValue JSMessageEvent::getConstructor(VM& vm, const JSGlobalObject* globalObjec JSC_DEFINE_CUSTOM_GETTER(jsMessageEventConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSMessagePort.cpp b/src/bun.js/bindings/webcore/JSMessagePort.cpp index c1c662899cea3d..45e80a8ba5ff3d 100644 --- a/src/bun.js/bindings/webcore/JSMessagePort.cpp +++ b/src/bun.js/bindings/webcore/JSMessagePort.cpp @@ -175,7 +175,7 @@ JSValue JSMessagePort::getConstructor(VM& vm, const JSGlobalObject* globalObject JSC_DEFINE_CUSTOM_GETTER(jsMessagePortConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformance.cpp b/src/bun.js/bindings/webcore/JSPerformance.cpp index 8d10c604e396f0..862cbc4d1cb54c 100644 --- a/src/bun.js/bindings/webcore/JSPerformance.cpp +++ b/src/bun.js/bindings/webcore/JSPerformance.cpp @@ -130,7 +130,7 @@ JSC_DEFINE_HOST_FUNCTION(functionPerformanceNow, (JSGlobalObject * globalObject, JSC_DEFINE_JIT_OPERATION(functionPerformanceNowWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSPerformance* castedThis)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); IGNORE_WARNINGS_BEGIN("frame-address") CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END @@ -307,7 +307,7 @@ JSValue JSPerformance::getConstructor(VM& vm, const JSGlobalObject* globalObject JSC_DEFINE_CUSTOM_GETTER(jsPerformanceConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformanceEntry.cpp b/src/bun.js/bindings/webcore/JSPerformanceEntry.cpp index 924cc6f7fb87e4..91096d92c77932 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceEntry.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceEntry.cpp @@ -166,7 +166,7 @@ void JSPerformanceEntry::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsPerformanceEntryConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformanceMark.cpp b/src/bun.js/bindings/webcore/JSPerformanceMark.cpp index 4e26dafd0dc7c4..3fe0c5162c9c4a 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceMark.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceMark.cpp @@ -90,7 +90,7 @@ using JSPerformanceMarkDOMConstructor = JSDOMConstructor; template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSPerformanceMarkDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -178,7 +178,7 @@ JSValue JSPerformanceMark::getConstructor(VM& vm, const JSGlobalObject* globalOb JSC_DEFINE_CUSTOM_GETTER(jsPerformanceMarkConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformanceMarkOptions.cpp b/src/bun.js/bindings/webcore/JSPerformanceMarkOptions.cpp index 1a7ff1fbe3fa12..77a6362b1f617a 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceMarkOptions.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceMarkOptions.cpp @@ -30,7 +30,7 @@ using namespace JSC; template<> PerformanceMarkOptions convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSPerformanceMeasure.cpp b/src/bun.js/bindings/webcore/JSPerformanceMeasure.cpp index 824e3a3ac22258..9f0649e5c5aa6b 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceMeasure.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceMeasure.cpp @@ -144,7 +144,7 @@ JSValue JSPerformanceMeasure::getConstructor(VM& vm, const JSGlobalObject* globa JSC_DEFINE_CUSTOM_GETTER(jsPerformanceMeasureConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformanceMeasureOptions.cpp b/src/bun.js/bindings/webcore/JSPerformanceMeasureOptions.cpp index 8eaa6dd9cbc94f..498415c571402d 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceMeasureOptions.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceMeasureOptions.cpp @@ -33,7 +33,7 @@ using namespace JSC; template<> PerformanceMeasureOptions convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp b/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp index 7c1b2703be08a1..35ab9adf9d36d0 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceObserver.cpp @@ -59,7 +59,7 @@ using namespace JSC; template<> PerformanceObserver::Init convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); @@ -158,7 +158,7 @@ static const HashTableValue JSPerformanceObserverConstructorTableValues[] = { template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSPerformanceObserverDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -257,7 +257,7 @@ void JSPerformanceObserver::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsPerformanceObserverConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp b/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp index 435ca85cf09e20..d8a63e055fcb80 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceObserverEntryList.cpp @@ -164,7 +164,7 @@ void JSPerformanceObserverEntryList::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsPerformanceObserverEntryListConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSPerformanceResourceTiming.h b/src/bun.js/bindings/webcore/JSPerformanceResourceTiming.h index fead6a35907257..86e6b29327051d 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceResourceTiming.h +++ b/src/bun.js/bindings/webcore/JSPerformanceResourceTiming.h @@ -32,7 +32,7 @@ class JSPerformanceResourceTiming : public JSPerformanceEntry { using DOMWrapped = PerformanceResourceTiming; static JSPerformanceResourceTiming* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref&& impl) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSPerformanceResourceTiming* ptr = new (NotNull, JSC::allocateCell(vm)) JSPerformanceResourceTiming(structure, *globalObject, WTFMove(impl)); ptr->finishCreation(vm); return ptr; diff --git a/src/bun.js/bindings/webcore/JSPerformanceServerTiming.h b/src/bun.js/bindings/webcore/JSPerformanceServerTiming.h index 0096a938c249ee..7d549f368983ab 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceServerTiming.h +++ b/src/bun.js/bindings/webcore/JSPerformanceServerTiming.h @@ -31,7 +31,7 @@ class JSPerformanceServerTiming : public JSDOMWrapper { using Base = JSDOMWrapper; static JSPerformanceServerTiming* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref&& impl) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSPerformanceServerTiming* ptr = new (NotNull, JSC::allocateCell(vm)) JSPerformanceServerTiming(structure, *globalObject, WTFMove(impl)); ptr->finishCreation(vm); return ptr; diff --git a/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp b/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp index 6e5fcc303b8989..412dfdd4b75ed6 100644 --- a/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp +++ b/src/bun.js/bindings/webcore/JSPerformanceTiming.cpp @@ -199,7 +199,7 @@ void JSPerformanceTiming::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsPerformanceTimingConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSReadableByteStreamController.cpp b/src/bun.js/bindings/webcore/JSReadableByteStreamController.cpp index 5c21c427922072..83896c86b0195a 100644 --- a/src/bun.js/bindings/webcore/JSReadableByteStreamController.cpp +++ b/src/bun.js/bindings/webcore/JSReadableByteStreamController.cpp @@ -162,7 +162,7 @@ void JSReadableByteStreamController::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsReadableByteStreamControllerConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSReadableStream.cpp b/src/bun.js/bindings/webcore/JSReadableStream.cpp index 8f79cf3c799b20..a524a6689533d9 100644 --- a/src/bun.js/bindings/webcore/JSReadableStream.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStream.cpp @@ -226,7 +226,7 @@ void JSReadableStream::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsReadableStreamConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSReadableStreamBYOBReader.cpp b/src/bun.js/bindings/webcore/JSReadableStreamBYOBReader.cpp index 9568df1bcf0ba1..320597bf950c02 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamBYOBReader.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamBYOBReader.cpp @@ -161,7 +161,7 @@ void JSReadableStreamBYOBReader::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsReadableStreamBYOBReaderConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSReadableStreamBYOBRequest.cpp b/src/bun.js/bindings/webcore/JSReadableStreamBYOBRequest.cpp index 18f7c8834dbbd0..6e6687724f4066 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamBYOBRequest.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamBYOBRequest.cpp @@ -160,7 +160,7 @@ void JSReadableStreamBYOBRequest::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsReadableStreamBYOBRequestConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp b/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp index b69dde2844cc46..4863283b49bede 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp @@ -164,7 +164,7 @@ void JSReadableStreamDefaultController::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsReadableStreamDefaultControllerConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp b/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp index e86af40e38e3a6..676fd4fc6a8e76 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp @@ -164,7 +164,7 @@ void JSReadableStreamDefaultReader::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsReadableStreamDefaultReaderConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSStructuredSerializeOptions.cpp b/src/bun.js/bindings/webcore/JSStructuredSerializeOptions.cpp index 4311426e6e9561..cc6bb17125f9ba 100644 --- a/src/bun.js/bindings/webcore/JSStructuredSerializeOptions.cpp +++ b/src/bun.js/bindings/webcore/JSStructuredSerializeOptions.cpp @@ -31,7 +31,7 @@ using namespace JSC; template<> StructuredSerializeOptions convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSTextDecoderStream.h b/src/bun.js/bindings/webcore/JSTextDecoderStream.h index eecb62bdc8a276..34de4e992ac0a0 100644 --- a/src/bun.js/bindings/webcore/JSTextDecoderStream.h +++ b/src/bun.js/bindings/webcore/JSTextDecoderStream.h @@ -29,7 +29,7 @@ class JSTextDecoderStream : public JSDOMObject { using Base = JSDOMObject; static JSTextDecoderStream* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSTextDecoderStream* ptr = new (NotNull, JSC::allocateCell(vm)) JSTextDecoderStream(structure, *globalObject); ptr->finishCreation(vm); return ptr; diff --git a/src/bun.js/bindings/webcore/JSTextEncoder.cpp b/src/bun.js/bindings/webcore/JSTextEncoder.cpp index e33bf367ed0104..71bee1f94400a3 100644 --- a/src/bun.js/bindings/webcore/JSTextEncoder.cpp +++ b/src/bun.js/bindings/webcore/JSTextEncoder.cpp @@ -81,7 +81,7 @@ extern "C" JSC::EncodedJSValue TextEncoder__encodeRopeString(JSC::JSGlobalObject template<> TextEncoder::EncodeIntoResult convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); @@ -181,7 +181,7 @@ using JSTextEncoderDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSTextEncoderDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -247,7 +247,7 @@ static const HashTableValue JSTextEncoderPrototypeTableValues[] = { // JSC_DEFINE_JIT_OPERATION(jsTextEncoderEncodeWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSTextEncoder* castedThis, DOMJIT::IDLJSArgumentType input)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -281,7 +281,7 @@ static const HashTableValue JSTextEncoderPrototypeTableValues[] = { // JSC_DEFINE_JIT_OPERATION(jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeCheck, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, JSTextEncoder* castedThis, DOMJIT::IDLJSArgumentType sourceStr, DOMJIT::IDLJSArgumentType destination)) // { -// VM& vm = JSC::getVM(lexicalGlobalObject); +// auto& vm = JSC::getVM(lexicalGlobalObject); // IGNORE_WARNINGS_BEGIN("frame-address") // CallFrame* callFrame = DECLARE_CALL_FRAME(vm); // IGNORE_WARNINGS_END @@ -351,7 +351,7 @@ void JSTextEncoder::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsTextEncoderConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSTextEncoderStream.h b/src/bun.js/bindings/webcore/JSTextEncoderStream.h index 4db3bbbbd022b9..3ad0efb3d19487 100644 --- a/src/bun.js/bindings/webcore/JSTextEncoderStream.h +++ b/src/bun.js/bindings/webcore/JSTextEncoderStream.h @@ -29,7 +29,7 @@ class JSTextEncoderStream : public JSDOMObject { using Base = JSDOMObject; static JSTextEncoderStream* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSTextEncoderStream* ptr = new (NotNull, JSC::allocateCell(vm)) JSTextEncoderStream(structure, *globalObject); ptr->finishCreation(vm); return ptr; diff --git a/src/bun.js/bindings/webcore/JSTransformStream.cpp b/src/bun.js/bindings/webcore/JSTransformStream.cpp index 76488775aa0253..6ce71289c36cc6 100644 --- a/src/bun.js/bindings/webcore/JSTransformStream.cpp +++ b/src/bun.js/bindings/webcore/JSTransformStream.cpp @@ -156,7 +156,7 @@ void JSTransformStream::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsTransformStreamConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSTransformStreamDefaultController.cpp b/src/bun.js/bindings/webcore/JSTransformStreamDefaultController.cpp index 67309e62f1823a..8be090d13da1fd 100644 --- a/src/bun.js/bindings/webcore/JSTransformStreamDefaultController.cpp +++ b/src/bun.js/bindings/webcore/JSTransformStreamDefaultController.cpp @@ -161,7 +161,7 @@ void JSTransformStreamDefaultController::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsTransformStreamDefaultControllerConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp index 674d076eff134c..1828b958e42b48 100644 --- a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp +++ b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp @@ -118,7 +118,7 @@ using JSURLSearchParamsDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSURLSearchParamsDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -157,7 +157,7 @@ template<> void JSURLSearchParamsDOMConstructor::initializeProperties(VM& vm, JS JSC_DEFINE_CUSTOM_GETTER(jsURLSearchParamsPrototype_getLength, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!thisObject)) @@ -236,7 +236,7 @@ void JSURLSearchParams::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsURLSearchParamsConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSWebSocket.cpp b/src/bun.js/bindings/webcore/JSWebSocket.cpp index eb28767edc9c97..ba26a0389dbb4c 100644 --- a/src/bun.js/bindings/webcore/JSWebSocket.cpp +++ b/src/bun.js/bindings/webcore/JSWebSocket.cpp @@ -145,7 +145,7 @@ static_assert(WebSocket::CLOSED == 3, "CLOSED in WebSocket does not match value static inline JSC::EncodedJSValue constructJSWebSocket1(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -172,7 +172,7 @@ static inline JSC::EncodedJSValue constructJSWebSocket1(JSGlobalObject* lexicalG static inline JSC::EncodedJSValue constructJSWebSocket2(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -199,7 +199,7 @@ static inline JSC::EncodedJSValue constructJSWebSocket2(JSGlobalObject* lexicalG static inline JSC::EncodedJSValue constructJSWebSocket3(JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSValue urlValue, JSValue optionsObjectValue) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* globalObject = jsCast(lexicalGlobalObject); auto* context = globalObject->scriptExecutionContext(); @@ -262,7 +262,7 @@ static inline JSC::EncodedJSValue constructJSWebSocket3(JSGlobalObject* lexicalG template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWebSocketDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); UNUSED_PARAM(throwScope); size_t argsCount = std::min(2, callFrame->argumentCount()); @@ -374,7 +374,7 @@ JSValue JSWebSocket::getConstructor(VM& vm, const JSGlobalObject* globalObject) JSC_DEFINE_CUSTOM_GETTER(jsWebSocketConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSWorker.cpp b/src/bun.js/bindings/webcore/JSWorker.cpp index 57e9dd062b2a44..223aab42494006 100644 --- a/src/bun.js/bindings/webcore/JSWorker.cpp +++ b/src/bun.js/bindings/webcore/JSWorker.cpp @@ -113,7 +113,7 @@ using JSWorkerDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWorkerDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -380,7 +380,7 @@ JSValue JSWorker::getConstructor(VM& vm, const JSGlobalObject* globalObject) JSC_DEFINE_CUSTOM_GETTER(jsWorkerConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSWorkerOptions.cpp b/src/bun.js/bindings/webcore/JSWorkerOptions.cpp index cb46c6f204093a..96c654a9342ad1 100644 --- a/src/bun.js/bindings/webcore/JSWorkerOptions.cpp +++ b/src/bun.js/bindings/webcore/JSWorkerOptions.cpp @@ -32,7 +32,7 @@ using namespace JSC; template<> WorkerOptions convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcore/JSWritableStream.cpp b/src/bun.js/bindings/webcore/JSWritableStream.cpp index 14c202ab89a948..2753681e57aa3a 100644 --- a/src/bun.js/bindings/webcore/JSWritableStream.cpp +++ b/src/bun.js/bindings/webcore/JSWritableStream.cpp @@ -97,7 +97,7 @@ using JSWritableStreamDOMConstructor = JSDOMConstructor; template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWritableStreamDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* castedThis = jsCast(callFrame->jsCallee()); ASSERT(castedThis); @@ -196,7 +196,7 @@ void JSWritableStream::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsWritableStreamConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSWritableStreamDefaultController.cpp b/src/bun.js/bindings/webcore/JSWritableStreamDefaultController.cpp index 15b0097a6a2ff2..efc60f53b10ec7 100644 --- a/src/bun.js/bindings/webcore/JSWritableStreamDefaultController.cpp +++ b/src/bun.js/bindings/webcore/JSWritableStreamDefaultController.cpp @@ -157,7 +157,7 @@ void JSWritableStreamDefaultController::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsWritableStreamDefaultControllerConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/JSWritableStreamDefaultWriter.cpp b/src/bun.js/bindings/webcore/JSWritableStreamDefaultWriter.cpp index a9e758f6f11044..77464b656adf71 100644 --- a/src/bun.js/bindings/webcore/JSWritableStreamDefaultWriter.cpp +++ b/src/bun.js/bindings/webcore/JSWritableStreamDefaultWriter.cpp @@ -164,7 +164,7 @@ void JSWritableStreamDefaultWriter::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsWritableStreamDefaultWriterConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcore/ReadableStream.cpp b/src/bun.js/bindings/webcore/ReadableStream.cpp index 36828aaf156f4c..c6cf7882e1d4b7 100644 --- a/src/bun.js/bindings/webcore/ReadableStream.cpp +++ b/src/bun.js/bindings/webcore/ReadableStream.cpp @@ -242,7 +242,7 @@ bool ReadableStream::isDisturbed() const JSC_DEFINE_HOST_FUNCTION(jsFunctionTransferToNativeReadableStream, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* readableStream = jsDynamicCast(callFrame->argument(0)); diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index 7bb59bdfb12176..c86548ac0dc856 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -504,6 +504,7 @@ enum class CryptoAlgorithmIdentifierTag { HKDF = 20, PBKDF2 = 21, ED25519 = 22, + X25519 = 23, }; const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 22; @@ -2293,6 +2294,9 @@ class CloneSerializer : CloneBase { case CryptoAlgorithmIdentifier::Ed25519: write(CryptoAlgorithmIdentifierTag::ED25519); break; + case CryptoAlgorithmIdentifier::X25519: + write(CryptoAlgorithmIdentifierTag::X25519); + break; case CryptoAlgorithmIdentifier::None: { RELEASE_ASSERT_NOT_REACHED(); break; @@ -3777,6 +3781,9 @@ class CloneDeserializer : CloneBase { case CryptoAlgorithmIdentifierTag::ED25519: result = CryptoAlgorithmIdentifier::Ed25519; break; + case CryptoAlgorithmIdentifierTag::X25519: + result = CryptoAlgorithmIdentifier::X25519; + break; } return true; } @@ -5728,7 +5735,7 @@ RefPtr SerializedScriptValue::create(StringView string) RefPtr SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception) { JSGlobalObject* lexicalGlobalObject = toJS(originContext); - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); @@ -5916,7 +5923,7 @@ JSValue SerializedScriptValue::deserialize(JSGlobalObject& lexicalGlobalObject, JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception) { JSGlobalObject* lexicalGlobalObject = toJS(destinationContext); - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); diff --git a/src/bun.js/bindings/webcore/StructuredClone.cpp b/src/bun.js/bindings/webcore/StructuredClone.cpp index f0f8691bd23ba3..143451693df8b9 100644 --- a/src/bun.js/bindings/webcore/StructuredClone.cpp +++ b/src/bun.js/bindings/webcore/StructuredClone.cpp @@ -41,7 +41,7 @@ enum class CloneMode { static JSC::EncodedJSValue cloneArrayBufferImpl(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame, CloneMode mode) { - VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); ASSERT(lexicalGlobalObject); ASSERT(callFrame->argumentCount()); diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index b2c8622f943bbb..c35bf6c3e90569 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -1464,9 +1464,9 @@ extern "C" void WebSocket__didAbruptClose(WebCore::WebSocket* webSocket, int32_t { webSocket->didFailWithErrorCode(errorCode); } -extern "C" void WebSocket__didClose(WebCore::WebSocket* webSocket, uint16_t errorCode, const BunString* reason) +extern "C" void WebSocket__didClose(WebCore::WebSocket* webSocket, uint16_t errorCode, BunString* reason) { - WTF::String wtf_reason = reason->toWTFString(BunString::ZeroCopy); + WTF::String wtf_reason = reason->transferToWTFString(); webSocket->didClose(0, errorCode, WTFMove(wtf_reason)); } diff --git a/src/bun.js/bindings/webcore/Worker.cpp b/src/bun.js/bindings/webcore/Worker.cpp index 3b5d322b0bf64e..f55eaf567a2e01 100644 --- a/src/bun.js/bindings/webcore/Worker.cpp +++ b/src/bun.js/bindings/webcore/Worker.cpp @@ -136,9 +136,8 @@ void Worker::setKeepAlive(bool keepAlive) bool Worker::updatePtr() { if (!WebWorker__updatePtr(impl_, this)) { - m_wasTerminated = true; - m_isClosing = true; - m_isOnline = false; + m_onlineClosingFlags = ClosingFlag; + m_terminationFlags.fetch_or(TerminatedFlag); return false; } @@ -198,6 +197,8 @@ ExceptionOr> Worker::create(ScriptExecutionContext& context, const S execArgv ? static_cast(execArgv->size()) : 0, preloadModules.size() ? preloadModules.data() : nullptr, static_cast(preloadModules.size())); + // now referenced by Zig + worker->ref(); preloadModuleStrings->clear(); @@ -222,7 +223,7 @@ Worker::~Worker() ExceptionOr Worker::postMessage(JSC::JSGlobalObject& state, JSC::JSValue messageValue, StructuredSerializeOptions&& options) { - if (m_wasTerminated) + if (m_terminationFlags & TerminatedFlag) return Exception { InvalidStateError, "Worker has been terminated"_s }; Vector> ports; @@ -251,7 +252,7 @@ ExceptionOr Worker::postMessage(JSC::JSGlobalObject& state, JSC::JSValue m void Worker::terminate() { // m_contextProxy.terminateWorkerGlobalScope(); - m_wasTerminated = true; + m_terminationFlags.fetch_or(TerminateRequestedFlag); WebWorker__requestTerminate(impl_); } @@ -283,16 +284,17 @@ void Worker::terminate() bool Worker::hasPendingActivity() const { - if (this->m_isOnline) { - return !this->m_isClosing; + auto onlineClosingFlags = m_onlineClosingFlags.load(); + if (onlineClosingFlags & OnlineFlag) { + return !(onlineClosingFlags & ClosingFlag); } - return !this->m_wasTerminated; + return !(m_terminationFlags & TerminatedFlag); } void Worker::dispatchEvent(Event& event) { - if (!m_wasTerminated) + if (!m_terminationFlags) EventTargetWithInlineData::dispatchEvent(event); } @@ -338,7 +340,7 @@ void Worker::dispatchOnline(Zig::GlobalObject* workerGlobalObject) Locker lock(this->m_pendingTasksMutex); - this->m_isOnline = true; + m_onlineClosingFlags.fetch_or(OnlineFlag); auto* thisContext = workerGlobalObject->scriptExecutionContext(); if (!thisContext) { return; @@ -386,20 +388,19 @@ void Worker::dispatchExit(int32_t exitCode) return; ScriptExecutionContext::postTaskTo(ctx->identifier(), [exitCode, protectedThis = Ref { *this }](ScriptExecutionContext& context) -> void { - protectedThis->m_isOnline = false; - protectedThis->m_isClosing = true; + protectedThis->m_onlineClosingFlags = ClosingFlag; if (protectedThis->hasEventListeners(eventNames().closeEvent)) { auto event = CloseEvent::create(exitCode == 0, static_cast(exitCode), exitCode == 0 ? "Worker terminated normally"_s : "Worker exited abnormally"_s); protectedThis->dispatchCloseEvent(event); } - protectedThis->m_wasTerminated = true; + protectedThis->m_terminationFlags.fetch_or(TerminatedFlag); }); } void Worker::postTaskToWorkerGlobalScope(Function&& task) { - if (!this->m_isOnline) { + if (!(m_onlineClosingFlags & OnlineFlag)) { Locker lock(this->m_pendingTasksMutex); this->m_pendingTasks.append(WTFMove(task)); return; @@ -417,13 +418,12 @@ void Worker::forEachWorker(const Functionref(); worker->dispatchExit(exitCode); + // no longer referenced by Zig worker->deref(); if (globalObject) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); vm.setHasTerminationRequest(); { @@ -462,7 +462,7 @@ extern "C" WebCore::Worker* WebWorker__getParentWorker(void*); JSC_DEFINE_HOST_FUNCTION(jsReceiveMessageOnPort, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 1) { diff --git a/src/bun.js/bindings/webcore/Worker.h b/src/bun.js/bindings/webcore/Worker.h index a83f97bbbee930..9fe3aba7acf93f 100644 --- a/src/bun.js/bindings/webcore/Worker.h +++ b/src/bun.js/bindings/webcore/Worker.h @@ -68,7 +68,7 @@ class Worker final : public ThreadSafeRefCounted, public EventTargetWith using ThreadSafeRefCounted::ref; void terminate(); - bool wasTerminated() const { return m_wasTerminated; } + bool wasTerminated() const { return m_terminationFlags & TerminatedFlag; } bool hasPendingActivity() const; bool updatePtr(); @@ -120,6 +120,11 @@ class Worker final : public ThreadSafeRefCounted, public EventTargetWith static void networkStateChanged(bool isOnLine); + static constexpr uint8_t OnlineFlag = 1 << 0; + static constexpr uint8_t ClosingFlag = 1 << 1; + static constexpr uint8_t TerminateRequestedFlag = 1 << 0; + static constexpr uint8_t TerminatedFlag = 1 << 1; + // RefPtr m_scriptLoader; WorkerOptions m_options; String m_identifier; @@ -132,10 +137,11 @@ class Worker final : public ThreadSafeRefCounted, public EventTargetWith Deque> m_pendingEvents; Lock m_pendingTasksMutex; Deque> m_pendingTasks; - std::atomic m_wasTerminated { false }; bool m_didStartWorkerGlobalScope { false }; - bool m_isOnline { false }; - bool m_isClosing { false }; + // Tracks OnlineFlag and ClosingFlag + std::atomic m_onlineClosingFlags { 0 }; + // Tracks TerminateRequestedFlag and TerminatedFlag + std::atomic m_terminationFlags { 0 }; const ScriptExecutionContextIdentifier m_clientIdentifier; void* impl_ { nullptr }; }; diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp index f6350fe65d4f1f..318a8e15bef4df 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.cpp @@ -95,12 +95,10 @@ ExceptionOr CryptoAlgorithm::getKeyLength(const CryptoAlgorithmParameter template static void dispatchAlgorithmOperation(WorkQueue& workQueue, ScriptExecutionContext& context, ResultCallbackType&& callback, CryptoAlgorithm::ExceptionCallback&& exceptionCallback, OperationType&& operation) { - context.refEventLoop(); - workQueue.dispatch( + workQueue.dispatch(context.globalObject(), [operation = WTFMove(operation), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), contextIdentifier = context.identifier()]() mutable { auto result = operation(); ScriptExecutionContext::postTaskTo(contextIdentifier, [result = crossThreadCopy(WTFMove(result)), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](auto& context) mutable { - context.unrefEventLoop(); if (result.hasException()) { exceptionCallback(result.releaseException().code(), ""_s); return; diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h index 29964198d14926..97eb9a5c8015e7 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithm.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include "SubtleCrypto.h" #if ENABLE(WEB_CRYPTO) diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp index a26290f7aa56e9..acb047cc722bac 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDH.cpp @@ -110,7 +110,7 @@ void CryptoAlgorithmECDH::deriveBits(const CryptoAlgorithmParameters& parameters // This is a special case that can't use dispatchOperation() because it bundles // the result validation and callback dispatch into unifiedCallback. - workQueue.dispatch( + workQueue.dispatch(context.globalObject(), [baseKey = WTFMove(baseKey), publicKey = ecParameters.publicKey, length, unifiedCallback = WTFMove(unifiedCallback), contextIdentifier = context.identifier()]() mutable { auto derivedKey = platformDeriveBits(downcast(baseKey.get()), downcast(*publicKey)); ScriptExecutionContext::postTaskTo(contextIdentifier, [derivedKey = WTFMove(derivedKey), length, unifiedCallback = WTFMove(unifiedCallback)](auto&) mutable { diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h b/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h index d6a112ecb8abca..8f0ef468e8eda8 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmIdentifier.h @@ -50,7 +50,8 @@ enum class CryptoAlgorithmIdentifier : uint8_t { SHA_512, HKDF, PBKDF2, - Ed25519 + Ed25519, + X25519 }; } // namespace WebCore diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp index e2691e87a04c95..fb919908a2ae4d 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA1.cpp @@ -61,13 +61,10 @@ void CryptoAlgorithmSHA1::digest(Vector&& message, VectorCallback&& cal return; } - context.refEventLoop(); - - workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + workQueue.dispatch(context.globalObject(), [digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { - context.unrefEventLoop(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp index 9333c304adf380..7080ab025544a2 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA224.cpp @@ -61,12 +61,10 @@ void CryptoAlgorithmSHA224::digest(Vector&& message, VectorCallback&& c return; } - context.refEventLoop(); - workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + workQueue.dispatch(context.globalObject(), [digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { - context.unrefEventLoop(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp index c04dfc790c9110..d55e874155c64e 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA256.cpp @@ -60,12 +60,11 @@ void CryptoAlgorithmSHA256::digest(Vector&& message, VectorCallback&& c }); return; } - context.refEventLoop(); - workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + + workQueue.dispatch(context.globalObject(), [digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { - context.unrefEventLoop(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp index 0297099f985af7..a4237487d6ab9c 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA384.cpp @@ -61,13 +61,10 @@ void CryptoAlgorithmSHA384::digest(Vector&& message, VectorCallback&& c return; } - context.refEventLoop(); - - workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + workQueue.dispatch(context.globalObject(), [digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { - context.unrefEventLoop(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp index edb1f8b492b38f..e902cfa1d5e835 100644 --- a/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmSHA512.cpp @@ -61,13 +61,10 @@ void CryptoAlgorithmSHA512::digest(Vector&& message, VectorCallback&& c return; } - context.refEventLoop(); - workQueue.dispatch([digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { + workQueue.dispatch(context.globalObject(), [digest = WTFMove(digest), message = WTFMove(message), callback = WTFMove(callback), contextIdentifier = context.identifier()]() mutable { digest->addBytes(message.data(), message.size()); auto result = digest->computeHash(); - - ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto& context) { - context.unrefEventLoop(); + ScriptExecutionContext::postTaskTo(contextIdentifier, [callback = WTFMove(callback), result = WTFMove(result)](auto&) { callback(result); }); }); diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp index 5d5e3c2ff35c08..09f9a5e726f382 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp @@ -38,12 +38,12 @@ namespace WebCore { bool CryptoKeyOKP::isPlatformSupportedCurve(NamedCurve namedCurve) { - return namedCurve == NamedCurve::Ed25519; + return namedCurve == NamedCurve::Ed25519 || namedCurve == NamedCurve::X25519; } std::optional CryptoKeyOKP::platformGeneratePair(CryptoAlgorithmIdentifier identifier, NamedCurve namedCurve, bool extractable, CryptoKeyUsageBitmap usages) { - if (namedCurve != NamedCurve::Ed25519) + if (namedCurve != NamedCurve::Ed25519 && namedCurve != NamedCurve::X25519) return {}; Vector public_key(ED25519_PUBLIC_KEY_LEN), private_key(ED25519_PRIVATE_KEY_LEN); diff --git a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp index b9fd88ae772914..621ab9a94fbd4e 100644 --- a/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesCbcCfbParams.cpp @@ -37,7 +37,7 @@ using namespace JSC; template<> CryptoAlgorithmAesCbcCfbParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp b/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp index fd21f0d58c3255..aaf9fe693a875f 100644 --- a/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesCtrParams.cpp @@ -38,7 +38,7 @@ using namespace JSC; template<> CryptoAlgorithmAesCtrParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp b/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp index 94c8c6cc180452..38f65611a8747e 100644 --- a/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesGcmParams.cpp @@ -38,7 +38,7 @@ using namespace JSC; template<> CryptoAlgorithmAesGcmParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp index b7be2bca4c5456..226f1873dd771f 100644 --- a/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSAesKeyParams.cpp @@ -35,7 +35,7 @@ using namespace JSC; template<> CryptoAlgorithmAesKeyParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp index ba48c3da96c4d8..69a7da5fe1c83d 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoAesKeyAlgorithm.cpp @@ -37,7 +37,7 @@ using namespace JSC; template<> CryptoAesKeyAlgorithm convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp index 12ccfe8b0b2bc8..5953adb817755a 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoAlgorithmParameters.cpp @@ -34,7 +34,7 @@ using namespace JSC; template<> CryptoAlgorithmParameters convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp index f86d63c3f1f850..9d83056c98a082 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoEcKeyAlgorithm.cpp @@ -36,7 +36,7 @@ using namespace JSC; template<> CryptoEcKeyAlgorithm convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp index fd0a85740e1597..432d1a64cb32d8 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoHmacKeyAlgorithm.cpp @@ -38,7 +38,7 @@ using namespace JSC; template<> CryptoHmacKeyAlgorithm convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp index 45887d719af51b..fdc7b5225c345c 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp @@ -185,7 +185,7 @@ JSCryptoKey* JSCryptoKey::fromJS(JSGlobalObject* globalObject, JSValue value) return nullptr; } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto& names = WebCore::builtinNames(vm); @@ -243,7 +243,7 @@ void JSCryptoKey::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsCryptoKeyConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp index aee7a47e8cced6..c9291dd657a0fd 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyAlgorithm.cpp @@ -36,7 +36,7 @@ using namespace JSC; template<> CryptoKeyAlgorithm convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp index b0b7ae2fe451fd..f5476207eb4e4b 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyPair.cpp @@ -37,7 +37,7 @@ using namespace JSC; template<> CryptoKeyPair convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp index 4b6393f9800d42..52e9e84e2b68f0 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaHashedKeyAlgorithm.cpp @@ -39,7 +39,7 @@ using namespace JSC; template<> CryptoRsaHashedKeyAlgorithm convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp index a75d16791cad42..8b03a3ede05f84 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoRsaKeyAlgorithm.cpp @@ -38,7 +38,7 @@ using namespace JSC; template<> CryptoRsaKeyAlgorithm convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp index 7dfb4c136ca6d3..b3a60384ea04b3 100644 --- a/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSEcKeyParams.cpp @@ -34,7 +34,7 @@ using namespace JSC; template<> CryptoAlgorithmEcKeyParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp index cae7acd814ed22..a71096e3335ae1 100644 --- a/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSEcdhKeyDeriveParams.cpp @@ -36,7 +36,7 @@ using namespace JSC; template<> CryptoAlgorithmEcdhKeyDeriveParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp b/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp index b31e0bea2ca22d..18d4f6a19d36e6 100644 --- a/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSEcdsaParams.cpp @@ -37,7 +37,7 @@ using namespace JSC; template<> CryptoAlgorithmEcdsaParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp b/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp index 01d5856320ff98..f26320bb95570d 100644 --- a/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSHkdfParams.cpp @@ -38,7 +38,7 @@ using namespace JSC; template<> CryptoAlgorithmHkdfParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp index 48bd232531e6b6..37948bae040343 100644 --- a/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSHmacKeyParams.cpp @@ -38,7 +38,7 @@ using namespace JSC; template<> CryptoAlgorithmHmacKeyParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp index 1f7847fc9dc632..b5dc06196b089d 100644 --- a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp @@ -42,7 +42,7 @@ using namespace JSC; template<> JsonWebKey convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp index 157b2685e35b69..81d0db21bc9eb0 100644 --- a/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp +++ b/src/bun.js/bindings/webcrypto/JSPbkdf2Params.cpp @@ -39,7 +39,7 @@ using namespace JSC; template<> CryptoAlgorithmPbkdf2Params convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp index 25170eacc6d809..9b16b1a9e2bafd 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedImportParams.cpp @@ -37,7 +37,7 @@ using namespace JSC; template<> CryptoAlgorithmRsaHashedImportParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp index 59875582cf90ed..3c077ebd00e8d0 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaHashedKeyGenParams.cpp @@ -39,7 +39,7 @@ using namespace JSC; template<> CryptoAlgorithmRsaHashedKeyGenParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp index 4f338bf9d16fb0..873716b3c415f5 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaKeyGenParams.cpp @@ -36,7 +36,7 @@ using namespace JSC; template<> CryptoAlgorithmRsaKeyGenParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp index e0d461f1f95340..803481da6daf2e 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaOaepParams.cpp @@ -37,7 +37,7 @@ using namespace JSC; template<> CryptoAlgorithmRsaOaepParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp index ce10023e6cbcd7..78fa21466f99d0 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaOtherPrimesInfo.cpp @@ -36,7 +36,7 @@ using namespace JSC; template<> RsaOtherPrimesInfo convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp b/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp index b93dfa2ffad429..470b9527c51872 100644 --- a/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp +++ b/src/bun.js/bindings/webcrypto/JSRsaPssParams.cpp @@ -35,7 +35,7 @@ using namespace JSC; template<> CryptoAlgorithmRsaPssParams convertDictionary(JSGlobalObject& lexicalGlobalObject, JSValue value) { - VM& vm = JSC::getVM(&lexicalGlobalObject); + auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp index 7120ed30a7a94c..1b96063195051c 100644 --- a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp @@ -250,7 +250,7 @@ void JSSubtleCrypto::destroy(JSC::JSCell* cell) JSC_DEFINE_CUSTOM_GETTER(jsSubtleCryptoConstructor, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* prototype = jsDynamicCast(JSValue::decode(thisValue)); if (UNLIKELY(!prototype)) diff --git a/src/bun.js/bindings/webcrypto/PhonyWorkQueue.cpp b/src/bun.js/bindings/webcrypto/PhonyWorkQueue.cpp new file mode 100644 index 00000000000000..325ce6ad0273e6 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/PhonyWorkQueue.cpp @@ -0,0 +1,21 @@ +#include "PhonyWorkQueue.h" + +#include +#include "EventLoopTaskNoContext.h" + +namespace Bun { + +Ref PhonyWorkQueue::create(WTF::ASCIILiteral name) +{ + (void)name; + return adoptRef(*new PhonyWorkQueue); +} + +extern "C" void ConcurrentCppTask__createAndRun(EventLoopTaskNoContext* task); + +void PhonyWorkQueue::dispatch(JSC::JSGlobalObject* globalObject, WTF::Function&& function) +{ + ConcurrentCppTask__createAndRun(new EventLoopTaskNoContext(globalObject, WTFMove(function))); +} + +} // namespace Bun diff --git a/src/bun.js/bindings/webcrypto/PhonyWorkQueue.h b/src/bun.js/bindings/webcrypto/PhonyWorkQueue.h new file mode 100644 index 00000000000000..7d225bee3d74c9 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/PhonyWorkQueue.h @@ -0,0 +1,19 @@ +#pragma once + +#include "root.h" +#include +#include + +namespace Bun { + +// Work queue which really uses CppTask.Concurrent in Bun's event loop (which enqueues into a WorkPool). +// Maintained so that SubtleCrypto functions can pretend they're using a WorkQueue, even though +// WTF::WorkQueue doesn't work and we need to use Bun's equivalent. +class PhonyWorkQueue : public WTF::RefCounted { +public: + static Ref create(WTF::ASCIILiteral name); + + void dispatch(JSC::JSGlobalObject* globalObject, Function&&); +}; + +}; // namespace Bun diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp index cf0c2ae915fd92..eb6cc11ee65d5c 100644 --- a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp @@ -260,6 +260,9 @@ static ExceptionOr> normalizeCryptoAl case CryptoAlgorithmIdentifier::Ed25519: result = makeUnique(params); break; + case CryptoAlgorithmIdentifier::X25519: + result = makeUnique(params); + break; default: return Exception { NotSupportedError }; } @@ -328,6 +331,7 @@ static ExceptionOr> normalizeCryptoAl case CryptoAlgorithmIdentifier::AES_CFB: case CryptoAlgorithmIdentifier::AES_KW: case CryptoAlgorithmIdentifier::Ed25519: + case CryptoAlgorithmIdentifier::X25519: result = makeUnique(params); break; case CryptoAlgorithmIdentifier::HMAC: { @@ -540,6 +544,7 @@ static bool isSupportedExportKey(JSGlobalObject& state, CryptoAlgorithmIdentifie case CryptoAlgorithmIdentifier::ECDSA: case CryptoAlgorithmIdentifier::ECDH: case CryptoAlgorithmIdentifier::Ed25519: + case CryptoAlgorithmIdentifier::X25519: return true; default: return false; diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.h b/src/bun.js/bindings/webcrypto/SubtleCrypto.h index dbfee4649bf5f2..cd4f68ddb48102 100644 --- a/src/bun.js/bindings/webcrypto/SubtleCrypto.h +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include "PhonyWorkQueue.h" namespace JSC { class ArrayBufferView; @@ -44,6 +44,8 @@ class CallFrame; namespace WebCore { +using WorkQueue = Bun::PhonyWorkQueue; + struct JsonWebKey; class BufferSource; diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 242103874ec0ca..1b8d98eef498b5 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -1,29 +1,25 @@ const std = @import("std"); const JSC = bun.JSC; -const JSGlobalObject = JSC.JSGlobalObject; -const VirtualMachine = JSC.VirtualMachine; +const VirtualMachine = bun.JSC.VirtualMachine; const Allocator = std.mem.Allocator; const Lock = bun.Mutex; const bun = @import("root").bun; const Environment = bun.Environment; const Fetch = JSC.WebCore.Fetch; -const WebCore = JSC.WebCore; const Bun = JSC.API.Bun; const TaggedPointerUnion = @import("../tagged_pointer.zig").TaggedPointerUnion; const typeBaseName = @import("../meta.zig").typeBaseName; const AsyncGlobWalkTask = JSC.API.Glob.WalkTask.AsyncGlobWalkTask; -const CopyFilePromiseTask = WebCore.Blob.Store.CopyFile.CopyFilePromiseTask; +const CopyFilePromiseTask = bun.JSC.WebCore.Blob.Store.CopyFilePromiseTask; const AsyncTransformTask = JSC.API.JSTranspiler.TransformTask.AsyncTransformTask; -const ReadFileTask = WebCore.Blob.ReadFile.ReadFileTask; -const WriteFileTask = WebCore.Blob.WriteFile.WriteFileTask; +const ReadFileTask = bun.JSC.WebCore.Blob.ReadFileTask; +const WriteFileTask = bun.JSC.WebCore.Blob.WriteFileTask; const napi_async_work = JSC.napi.napi_async_work; const FetchTasklet = Fetch.FetchTasklet; const S3 = bun.S3; const S3HttpSimpleTask = S3.S3HttpSimpleTask; const S3HttpDownloadStreamingTask = S3.S3HttpDownloadStreamingTask; -const JSValue = JSC.JSValue; -const js = JSC.C; const Waker = bun.Async.Waker; pub const WorkPool = @import("../work_pool.zig").WorkPool; @@ -40,7 +36,7 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type { event_loop: *JSC.EventLoop, allocator: std.mem.Allocator, promise: JSC.JSPromise.Strong = .{}, - globalThis: *JSGlobalObject, + globalThis: *JSC.JSGlobalObject, concurrent_task: JSC.ConcurrentTask = .{}, // This is a poll because we want it to enter the uSockets loop @@ -48,7 +44,7 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type { pub usingnamespace bun.New(@This()); - pub fn createOnJSThread(allocator: std.mem.Allocator, globalThis: *JSGlobalObject, value: *Context) !*This { + pub fn createOnJSThread(allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, value: *Context) !*This { var this = This.new(.{ .event_loop = VirtualMachine.get().event_loop, .ctx = value, @@ -101,7 +97,7 @@ pub fn WorkTask(comptime Context: type) type { task: TaskType = .{ .callback = &runFromThreadPool }, event_loop: *JSC.EventLoop, allocator: std.mem.Allocator, - globalThis: *JSGlobalObject, + globalThis: *JSC.JSGlobalObject, concurrent_task: ConcurrentTask = .{}, async_task_tracker: JSC.AsyncTaskTracker, @@ -110,7 +106,7 @@ pub fn WorkTask(comptime Context: type) type { pub usingnamespace bun.New(@This()); - pub fn createOnJSThread(allocator: std.mem.Allocator, globalThis: *JSGlobalObject, value: *Context) !*This { + pub fn createOnJSThread(allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, value: *Context) !*This { var vm = globalThis.bunVM(); var this = This.new(.{ .event_loop = vm.eventLoop(), @@ -298,12 +294,61 @@ pub const AnyTaskWithExtraContext = struct { }; pub const CppTask = opaque { - extern fn Bun__performTask(globalObject: *JSGlobalObject, task: *CppTask) void; - pub fn run(this: *CppTask, global: *JSGlobalObject) void { + extern fn Bun__performTask(globalObject: *JSC.JSGlobalObject, task: *CppTask) void; + pub fn run(this: *CppTask, global: *JSC.JSGlobalObject) void { JSC.markBinding(@src()); Bun__performTask(global, this); } }; + +pub const ConcurrentCppTask = struct { + cpp_task: *EventLoopTaskNoContext, + workpool_task: JSC.WorkPoolTask = .{ .callback = &runFromWorkpool }, + + const EventLoopTaskNoContext = opaque { + extern fn Bun__EventLoopTaskNoContext__performTask(task: *EventLoopTaskNoContext) void; + extern fn Bun__EventLoopTaskNoContext__createdInBunVm(task: *const EventLoopTaskNoContext) ?*VirtualMachine; + + /// Deallocates `this` + pub fn run(this: *EventLoopTaskNoContext) void { + Bun__EventLoopTaskNoContext__performTask(this); + } + + /// Get the VM that created this task + pub fn getVM(this: *const EventLoopTaskNoContext) ?*VirtualMachine { + return Bun__EventLoopTaskNoContext__createdInBunVm(this); + } + }; + + pub fn runFromWorkpool(task: *JSC.WorkPoolTask) void { + var this: *ConcurrentCppTask = @fieldParentPtr("workpool_task", task); + // Extract all the info we need from `this` and `cpp_task` before we call functions that + // free them + const cpp_task = this.cpp_task; + const maybe_vm = cpp_task.getVM(); + this.destroy(); + cpp_task.run(); + if (maybe_vm) |vm| { + vm.event_loop.unrefConcurrently(); + } + } + + pub usingnamespace bun.New(@This()); + + pub export fn ConcurrentCppTask__createAndRun(cpp_task: *EventLoopTaskNoContext) void { + JSC.markBinding(@src()); + if (cpp_task.getVM()) |vm| { + vm.event_loop.refConcurrently(); + } + const cpp = ConcurrentCppTask.new(.{ .cpp_task = cpp_task }); + JSC.WorkPool.schedule(&cpp.workpool_task); + } +}; + +comptime { + _ = ConcurrentCppTask.ConcurrentCppTask__createAndRun; +} + pub const JSCScheduler = struct { pub const JSCDeferredWorkTask = opaque { extern fn Bun__runDeferredWork(task: *JSCScheduler.JSCDeferredWorkTask) void; @@ -409,6 +454,7 @@ const ProcessMiniEventLoopWaiterThreadTask = if (Environment.isPosix) bun.spawn. const ShellAsyncSubprocessDone = bun.shell.Interpreter.Cmd.ShellAsyncSubprocessDone; const RuntimeTranspilerStore = JSC.RuntimeTranspilerStore; const ServerAllConnectionsClosedTask = @import("./api/server.zig").ServerAllConnectionsClosedTask; +const FlushPendingFileSinkTask = JSC.WebCore.FlushPendingFileSinkTask; // Task.get(ReadFileTask) -> ?ReadFileTask pub const Task = TaggedPointerUnion(.{ @@ -461,6 +507,7 @@ pub const Task = TaggedPointerUnion(.{ ReadFileTask, Readlink, Readv, + FlushPendingFileSinkTask, Realpath, RealpathNonNative, Rename, @@ -499,7 +546,7 @@ pub const Task = TaggedPointerUnion(.{ }); const UnboundedQueue = @import("./unbounded_queue.zig").UnboundedQueue; pub const ConcurrentTask = struct { - task: if (JSC.is_bindgen) void else Task = undefined, + task: Task = undefined, next: ?*ConcurrentTask = null, auto_delete: bool = false, @@ -607,7 +654,7 @@ pub const GarbageCollectionController = struct { // // When the heap size is increasing, we always switch to fast mode // When the heap size has been the same or less for 30 seconds, we switch to slow mode - pub fn updateGCRepeatTimer(this: *GarbageCollectionController, comptime setting: @Type(.EnumLiteral)) void { + pub fn updateGCRepeatTimer(this: *GarbageCollectionController, comptime setting: @Type(.enum_literal)) void { if (setting == .fast and !this.gc_repeating_timer_fast) { this.gc_repeating_timer_fast = true; this.gc_repeating_timer.set(this, onGCRepeatingTimer, this.gc_timer_interval, this.gc_timer_interval); @@ -693,13 +740,11 @@ pub const GarbageCollectionController = struct { export fn Bun__tickWhilePaused(paused: *bool) void { JSC.markBinding(@src()); - JSC.VirtualMachine.get().eventLoop().tickWhilePaused(paused); + VirtualMachine.get().eventLoop().tickWhilePaused(paused); } comptime { - if (!JSC.is_bindgen) { - _ = Bun__tickWhilePaused; - } + _ = Bun__tickWhilePaused; } /// Sometimes, you have work that will be scheduled, cancelled, and rescheduled multiple times @@ -782,8 +827,8 @@ pub const EventLoop = struct { next_immediate_tasks: Queue = undefined, concurrent_tasks: ConcurrentTask.Queue = ConcurrentTask.Queue{}, - global: *JSGlobalObject = undefined, - virtual_machine: *JSC.VirtualMachine = undefined, + global: *JSC.JSGlobalObject = undefined, + virtual_machine: *VirtualMachine = undefined, waker: ?Waker = null, forever_timer: ?*uws.Timer = null, deferred_tasks: DeferredTaskQueue = .{}, @@ -792,12 +837,13 @@ pub const EventLoop = struct { debug: Debug = .{}, entered_event_loop_count: isize = 0, concurrent_ref: std.atomic.Value(i32) = std.atomic.Value(i32).init(0), + imminent_gc_timer: std.atomic.Value(?*JSC.BunTimer.WTFTimer) = .{ .raw = null }, signal_handler: if (Environment.isPosix) ?*PosixSignalHandle else void = if (Environment.isPosix) null, pub export fn Bun__ensureSignalHandler() void { if (Environment.isPosix) { - if (JSC.VirtualMachine.getMainThreadVM()) |vm| { + if (VirtualMachine.getMainThreadVM()) |vm| { const this = vm.eventLoop(); if (this.signal_handler == null) { this.signal_handler = PosixSignalHandle.new(.{}); @@ -847,14 +893,14 @@ pub const EventLoop = struct { defer this.debug.exit(); - if (count == 1) { + if (count == 1 and !this.virtual_machine.is_inside_deferred_task_queue) { this.drainMicrotasksWithGlobal(this.global, this.virtual_machine.jsc); } this.entered_event_loop_count -= 1; } - pub inline fn getVmImpl(this: *EventLoop) *JSC.VirtualMachine { + pub inline fn getVmImpl(this: *EventLoop) *VirtualMachine { return this.virtual_machine; } @@ -877,7 +923,10 @@ pub const EventLoop = struct { jsc_vm.releaseWeakRefs(); JSC__JSGlobalObject__drainMicrotasks(globalObject); + + this.virtual_machine.is_inside_deferred_task_queue = true; this.deferred_tasks.run(); + this.virtual_machine.is_inside_deferred_task_queue = false; if (comptime bun.Environment.isDebug) { this.debug.drain_microtasks_count_outside_tick_queue += @as(usize, @intFromBool(!this.debug.is_inside_tick_queue)); @@ -954,76 +1003,75 @@ pub const EventLoop = struct { while (@field(this, queue_name).readItem()) |task| { defer counter += 1; switch (task.tag()) { - @field(Task.Tag, typeBaseName(@typeName(ShellAsync))) => { + @field(Task.Tag, @typeName(ShellAsync)) => { var shell_ls_task: *ShellAsync = task.get(ShellAsync).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellAsyncSubprocessDone))) => { + @field(Task.Tag, @typeName(ShellAsyncSubprocessDone)) => { var shell_ls_task: *ShellAsyncSubprocessDone = task.get(ShellAsyncSubprocessDone).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellIOWriterAsyncDeinit))) => { + @field(Task.Tag, @typeName(ShellIOWriterAsyncDeinit)) => { var shell_ls_task: *ShellIOWriterAsyncDeinit = task.get(ShellIOWriterAsyncDeinit).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellIOReaderAsyncDeinit))) => { + @field(Task.Tag, @typeName(ShellIOReaderAsyncDeinit)) => { var shell_ls_task: *ShellIOReaderAsyncDeinit = task.get(ShellIOReaderAsyncDeinit).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellCondExprStatTask))) => { + @field(Task.Tag, @typeName(ShellCondExprStatTask)) => { var shell_ls_task: *ShellCondExprStatTask = task.get(ShellCondExprStatTask).?; shell_ls_task.task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellCpTask))) => { + @field(Task.Tag, @typeName(ShellCpTask)) => { var shell_ls_task: *ShellCpTask = task.get(ShellCpTask).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellTouchTask))) => { + @field(Task.Tag, @typeName(ShellTouchTask)) => { var shell_ls_task: *ShellTouchTask = task.get(ShellTouchTask).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellMkdirTask))) => { + @field(Task.Tag, @typeName(ShellMkdirTask)) => { var shell_ls_task: *ShellMkdirTask = task.get(ShellMkdirTask).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellLsTask))) => { + @field(Task.Tag, @typeName(ShellLsTask)) => { var shell_ls_task: *ShellLsTask = task.get(ShellLsTask).?; shell_ls_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellMvBatchedTask))) => { + @field(Task.Tag, @typeName(ShellMvBatchedTask)) => { var shell_mv_batched_task: *ShellMvBatchedTask = task.get(ShellMvBatchedTask).?; shell_mv_batched_task.task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellMvCheckTargetTask))) => { + @field(Task.Tag, @typeName(ShellMvCheckTargetTask)) => { var shell_mv_check_target_task: *ShellMvCheckTargetTask = task.get(ShellMvCheckTargetTask).?; shell_mv_check_target_task.task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellRmTask))) => { + @field(Task.Tag, @typeName(ShellRmTask)) => { var shell_rm_task: *ShellRmTask = task.get(ShellRmTask).?; shell_rm_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellRmDirTask))) => { + @field(Task.Tag, @typeName(ShellRmDirTask)) => { var shell_rm_task: *ShellRmDirTask = task.get(ShellRmDirTask).?; shell_rm_task.runFromMainThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ShellGlobTask))) => { + @field(Task.Tag, @typeName(ShellGlobTask)) => { var shell_glob_task: *ShellGlobTask = task.get(ShellGlobTask).?; shell_glob_task.runFromMainThread(); shell_glob_task.deinit(); }, - .FetchTasklet => { + @field(Task.Tag, @typeName(FetchTasklet)) => { var fetch_task: *Fetch.FetchTasklet = task.get(Fetch.FetchTasklet).?; fetch_task.onProgressUpdate(); }, - .S3HttpSimpleTask => { + @field(Task.Tag, @typeName(S3HttpSimpleTask)) => { var s3_task: *S3HttpSimpleTask = task.get(S3HttpSimpleTask).?; s3_task.onResponse(); }, - .S3HttpDownloadStreamingTask => { + @field(Task.Tag, @typeName(S3HttpDownloadStreamingTask)) => { var s3_task: *S3HttpDownloadStreamingTask = task.get(S3HttpDownloadStreamingTask).?; s3_task.onResponse(); }, - @field(Task.Tag, @typeName(AsyncGlobWalkTask)) => { var globWalkTask: *AsyncGlobWalkTask = task.get(AsyncGlobWalkTask).?; globWalkTask.*.runFromJS(); @@ -1039,11 +1087,11 @@ pub const EventLoop = struct { transform_task.*.runFromJS(); transform_task.deinit(); }, - @field(Task.Tag, typeBaseName(@typeName(JSC.napi.napi_async_work))) => { + @field(Task.Tag, @typeName(JSC.napi.napi_async_work)) => { const transform_task: *JSC.napi.napi_async_work = task.get(JSC.napi.napi_async_work).?; transform_task.*.runFromJS(); }, - .ThreadSafeFunction => { + @field(Task.Tag, @typeName(ThreadSafeFunction)) => { var transform_task: *ThreadSafeFunction = task.as(ThreadSafeFunction); transform_task.onDispatch(); }, @@ -1052,7 +1100,7 @@ pub const EventLoop = struct { transform_task.*.runFromJS(); transform_task.deinit(); }, - @field(Task.Tag, bun.meta.typeBaseName(@typeName(JSCDeferredWorkTask))) => { + @field(Task.Tag, @typeName(JSCDeferredWorkTask)) => { var jsc_task: *JSCDeferredWorkTask = task.get(JSCDeferredWorkTask).?; JSC.markBinding(@src()); jsc_task.run(); @@ -1069,237 +1117,241 @@ pub const EventLoop = struct { // special case: we return return 0; }, - @field(Task.Tag, typeBaseName(@typeName(bun.bake.DevServer.HotReloadEvent))) => { + @field(Task.Tag, @typeName(bun.bake.DevServer.HotReloadEvent)) => { const hmr_task: *bun.bake.DevServer.HotReloadEvent = task.get(bun.bake.DevServer.HotReloadEvent).?; hmr_task.run(); }, - @field(Task.Tag, typeBaseName(@typeName(FSWatchTask))) => { + @field(Task.Tag, @typeName(FSWatchTask)) => { var transform_task: *FSWatchTask = task.get(FSWatchTask).?; transform_task.*.run(); transform_task.deinit(); }, - @field(Task.Tag, typeBaseName(@typeName(AnyTask))) => { + @field(Task.Tag, @typeName(AnyTask)) => { var any: *AnyTask = task.get(AnyTask).?; any.run(); }, - @field(Task.Tag, typeBaseName(@typeName(ManagedTask))) => { + @field(Task.Tag, @typeName(ManagedTask)) => { var any: *ManagedTask = task.get(ManagedTask).?; any.run(); }, - @field(Task.Tag, typeBaseName(@typeName(CppTask))) => { + @field(Task.Tag, @typeName(CppTask)) => { var any: *CppTask = task.get(CppTask).?; any.run(global); }, - @field(Task.Tag, typeBaseName(@typeName(PollPendingModulesTask))) => { + @field(Task.Tag, @typeName(PollPendingModulesTask)) => { virtual_machine.modules.onPoll(); }, - @field(Task.Tag, typeBaseName(@typeName(GetAddrInfoRequestTask))) => { + @field(Task.Tag, @typeName(GetAddrInfoRequestTask)) => { if (Environment.os == .windows) @panic("This should not be reachable on Windows"); var any: *GetAddrInfoRequestTask = task.get(GetAddrInfoRequestTask).?; any.runFromJS(); any.deinit(); }, - @field(Task.Tag, typeBaseName(@typeName(Stat))) => { + @field(Task.Tag, @typeName(Stat)) => { var any: *Stat = task.get(Stat).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Lstat))) => { + @field(Task.Tag, @typeName(Lstat)) => { var any: *Lstat = task.get(Lstat).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Fstat))) => { + @field(Task.Tag, @typeName(Fstat)) => { var any: *Fstat = task.get(Fstat).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Open))) => { + @field(Task.Tag, @typeName(Open)) => { var any: *Open = task.get(Open).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ReadFile))) => { + @field(Task.Tag, @typeName(ReadFile)) => { var any: *ReadFile = task.get(ReadFile).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(WriteFile))) => { + @field(Task.Tag, @typeName(WriteFile)) => { var any: *WriteFile = task.get(WriteFile).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(CopyFile))) => { + @field(Task.Tag, @typeName(CopyFile)) => { var any: *CopyFile = task.get(CopyFile).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Read))) => { + @field(Task.Tag, @typeName(Read)) => { var any: *Read = task.get(Read).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Write))) => { + @field(Task.Tag, @typeName(Write)) => { var any: *Write = task.get(Write).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Truncate))) => { + @field(Task.Tag, @typeName(Truncate)) => { var any: *Truncate = task.get(Truncate).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Writev))) => { + @field(Task.Tag, @typeName(Writev)) => { var any: *Writev = task.get(Writev).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Readv))) => { + @field(Task.Tag, @typeName(Readv)) => { var any: *Readv = task.get(Readv).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Rename))) => { + @field(Task.Tag, @typeName(Rename)) => { var any: *Rename = task.get(Rename).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(FTruncate))) => { + @field(Task.Tag, @typeName(FTruncate)) => { var any: *FTruncate = task.get(FTruncate).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Readdir))) => { + @field(Task.Tag, @typeName(Readdir)) => { var any: *Readdir = task.get(Readdir).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ReaddirRecursive))) => { + @field(Task.Tag, @typeName(ReaddirRecursive)) => { var any: *ReaddirRecursive = task.get(ReaddirRecursive).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Close))) => { + @field(Task.Tag, @typeName(Close)) => { var any: *Close = task.get(Close).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Rm))) => { + @field(Task.Tag, @typeName(Rm)) => { var any: *Rm = task.get(Rm).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Rmdir))) => { + @field(Task.Tag, @typeName(Rmdir)) => { var any: *Rmdir = task.get(Rmdir).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Chown))) => { + @field(Task.Tag, @typeName(Chown)) => { var any: *Chown = task.get(Chown).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(FChown))) => { + @field(Task.Tag, @typeName(FChown)) => { var any: *FChown = task.get(FChown).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Utimes))) => { + @field(Task.Tag, @typeName(Utimes)) => { var any: *Utimes = task.get(Utimes).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Lutimes))) => { + @field(Task.Tag, @typeName(Lutimes)) => { var any: *Lutimes = task.get(Lutimes).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Chmod))) => { + @field(Task.Tag, @typeName(Chmod)) => { var any: *Chmod = task.get(Chmod).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Fchmod))) => { + @field(Task.Tag, @typeName(Fchmod)) => { var any: *Fchmod = task.get(Fchmod).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Link))) => { + @field(Task.Tag, @typeName(Link)) => { var any: *Link = task.get(Link).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Symlink))) => { + @field(Task.Tag, @typeName(Symlink)) => { var any: *Symlink = task.get(Symlink).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Readlink))) => { + @field(Task.Tag, @typeName(Readlink)) => { var any: *Readlink = task.get(Readlink).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Realpath))) => { + @field(Task.Tag, @typeName(Realpath)) => { var any: *Realpath = task.get(Realpath).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(RealpathNonNative))) => { + @field(Task.Tag, @typeName(RealpathNonNative)) => { var any: *RealpathNonNative = task.get(RealpathNonNative).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Mkdir))) => { + @field(Task.Tag, @typeName(Mkdir)) => { var any: *Mkdir = task.get(Mkdir).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Fsync))) => { + @field(Task.Tag, @typeName(Fsync)) => { var any: *Fsync = task.get(Fsync).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Fdatasync))) => { + @field(Task.Tag, @typeName(Fdatasync)) => { var any: *Fdatasync = task.get(Fdatasync).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Access))) => { + @field(Task.Tag, @typeName(Access)) => { var any: *Access = task.get(Access).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(AppendFile))) => { + @field(Task.Tag, @typeName(AppendFile)) => { var any: *AppendFile = task.get(AppendFile).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Mkdtemp))) => { + @field(Task.Tag, @typeName(Mkdtemp)) => { var any: *Mkdtemp = task.get(Mkdtemp).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Exists))) => { + @field(Task.Tag, @typeName(Exists)) => { var any: *Exists = task.get(Exists).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Futimes))) => { + @field(Task.Tag, @typeName(Futimes)) => { var any: *Futimes = task.get(Futimes).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Lchmod))) => { + @field(Task.Tag, @typeName(Lchmod)) => { var any: *Lchmod = task.get(Lchmod).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Lchown))) => { + @field(Task.Tag, @typeName(Lchown)) => { var any: *Lchown = task.get(Lchown).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(Unlink))) => { + @field(Task.Tag, @typeName(Unlink)) => { var any: *Unlink = task.get(Unlink).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(NativeZlib))) => { + @field(Task.Tag, @typeName(NativeZlib)) => { var any: *NativeZlib = task.get(NativeZlib).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(NativeBrotli))) => { + @field(Task.Tag, @typeName(NativeBrotli)) => { var any: *NativeBrotli = task.get(NativeBrotli).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(ProcessWaiterThreadTask))) => { + @field(Task.Tag, @typeName(ProcessWaiterThreadTask)) => { bun.markPosixOnly(); var any: *ProcessWaiterThreadTask = task.get(ProcessWaiterThreadTask).?; any.runFromJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(RuntimeTranspilerStore))) => { + @field(Task.Tag, @typeName(RuntimeTranspilerStore)) => { var any: *RuntimeTranspilerStore = task.get(RuntimeTranspilerStore).?; any.drain(); }, - @field(Task.Tag, typeBaseName(@typeName(TimerObject))) => { + @field(Task.Tag, @typeName(TimerObject)) => { var any: *TimerObject = task.get(TimerObject).?; any.runImmediateTask(virtual_machine); }, - @field(Task.Tag, typeBaseName(@typeName(ServerAllConnectionsClosedTask))) => { + @field(Task.Tag, @typeName(ServerAllConnectionsClosedTask)) => { var any: *ServerAllConnectionsClosedTask = task.get(ServerAllConnectionsClosedTask).?; any.runFromJSThread(virtual_machine); }, - @field(Task.Tag, typeBaseName(@typeName(bun.bundle_v2.DeferredBatchTask))) => { + @field(Task.Tag, @typeName(bun.bundle_v2.DeferredBatchTask)) => { var any: *bun.bundle_v2.DeferredBatchTask = task.get(bun.bundle_v2.DeferredBatchTask).?; any.runOnJSThread(); }, - @field(Task.Tag, typeBaseName(@typeName(PosixSignalTask))) => { + @field(Task.Tag, @typeName(PosixSignalTask)) => { PosixSignalTask.runFromJSThread(@intCast(task.asUintptr()), global); }, - @field(Task.Tag, typeBaseName(@typeName(StatFS))) => { + @field(Task.Tag, @typeName(StatFS)) => { var any: *StatFS = task.get(StatFS).?; any.runFromJSThread(); }, + @field(Task.Tag, @typeName(FlushPendingFileSinkTask)) => { + var any: *FlushPendingFileSinkTask = task.get(FlushPendingFileSinkTask).?; + any.runFromJSThread(); + }, else => { bun.Output.panic("Unexpected tag: {s}", .{@tagName(task.tag())}); @@ -1351,6 +1403,12 @@ pub const EventLoop = struct { } } + pub fn runImminentGCTimer(this: *EventLoop) void { + if (this.imminent_gc_timer.swap(null, .seq_cst)) |timer| { + timer.run(this.virtual_machine); + } + } + pub fn tickConcurrentWithCount(this: *EventLoop) usize { this.updateCounts(); @@ -1360,6 +1418,8 @@ pub const EventLoop = struct { } } + this.runImminentGCTimer(); + var concurrent = this.concurrent_tasks.popBatch(); const count = concurrent.count; if (count == 0) @@ -1429,12 +1489,14 @@ pub const EventLoop = struct { } } + this.runImminentGCTimer(); + if (loop.isActive()) { this.processGCTimer(); var event_loop_sleep_timer = if (comptime Environment.isDebug) std.time.Timer.start() catch unreachable; // for the printer, this is defined: var timespec: bun.timespec = if (Environment.isDebug) .{ .sec = 0, .nsec = 0 } else undefined; - loop.tickWithTimeout(if (ctx.timer.getTimeout(×pec)) ×pec else null); + loop.tickWithTimeout(if (ctx.timer.getTimeout(×pec, ctx)) ×pec else null); if (comptime Environment.isDebug) { log("tick {}, timeout: {}", .{ bun.fmt.fmtDuration(event_loop_sleep_timer.read()), bun.fmt.fmtDuration(timespec.ns()) }); @@ -1519,7 +1581,7 @@ pub const EventLoop = struct { this.processGCTimer(); var timespec: bun.timespec = undefined; - loop.tickWithTimeout(if (ctx.timer.getTimeout(×pec)) ×pec else null); + loop.tickWithTimeout(if (ctx.timer.getTimeout(×pec, ctx)) ×pec else null); } else { loop.tickWithoutIdle(); } @@ -1622,7 +1684,7 @@ pub const EventLoop = struct { const task = Task.from(timer.as(*anyopaque)); defer timer.deinit(true); - JSC.VirtualMachine.get().enqueueTask(task); + VirtualMachine.get().enqueueTask(task); } pub fn ensureWaker(this: *EventLoop) void { @@ -1702,9 +1764,9 @@ pub const EventLoop = struct { }; pub const JsVM = struct { - vm: *JSC.VirtualMachine, + vm: *VirtualMachine, - pub inline fn init(inner: *JSC.VirtualMachine) JsVM { + pub inline fn init(inner: *VirtualMachine) JsVM { return .{ .vm = inner, }; @@ -1778,25 +1840,25 @@ pub const EventLoopKind = enum { pub fn refType(comptime this: EventLoopKind) type { return switch (this) { - .js => *JSC.VirtualMachine, + .js => *VirtualMachine, .mini => *JSC.MiniEventLoop, }; } pub fn getVm(comptime this: EventLoopKind) EventLoopKind.refType(this) { return switch (this) { - .js => JSC.VirtualMachine.get(), + .js => VirtualMachine.get(), .mini => JSC.MiniEventLoop.global, }; } }; pub fn AbstractVM(inner: anytype) switch (@TypeOf(inner)) { - *JSC.VirtualMachine => JsVM, + *VirtualMachine => JsVM, *JSC.MiniEventLoop => MiniVM, else => @compileError("Invalid event loop ctx: " ++ @typeName(@TypeOf(inner))), } { - if (comptime @TypeOf(inner) == *JSC.VirtualMachine) return JsVM.init(inner); + if (comptime @TypeOf(inner) == *VirtualMachine) return JsVM.init(inner); if (comptime @TypeOf(inner) == *JSC.MiniEventLoop) return MiniVM.init(inner); @compileError("Invalid event loop ctx: " ++ @typeName(@TypeOf(inner))); } @@ -1818,8 +1880,8 @@ pub const MiniEventLoop = struct { after_event_loop_callback_ctx: ?*anyopaque = null, after_event_loop_callback: ?JSC.OpaqueCallback = null, pipe_read_buffer: ?*PipeReadBuffer = null, - stdout_store: ?*JSC.WebCore.Blob.Store = null, - stderr_store: ?*JSC.WebCore.Blob.Store = null, + stdout_store: ?*bun.JSC.WebCore.Blob.Store = null, + stderr_store: ?*bun.JSC.WebCore.Blob.Store = null, const PipeReadBuffer = [256 * 1024]u8; pub threadlocal var globalInitialized: bool = false; @@ -2198,6 +2260,14 @@ pub const EventLoopHandle = union(enum) { }; } + pub fn bunVM(this: EventLoopHandle) ?*VirtualMachine { + if (this == .js) { + return this.js.virtual_machine; + } + + return null; + } + pub fn stderr(this: EventLoopHandle) *JSC.WebCore.Blob.Store { return switch (this) { .js => this.js.virtual_machine.rareData().stderr(), @@ -2205,7 +2275,7 @@ pub const EventLoopHandle = union(enum) { }; } - pub fn cast(this: EventLoopHandle, comptime as: @Type(.EnumLiteral)) if (as == .js) *JSC.EventLoop else *MiniEventLoop { + pub fn cast(this: EventLoopHandle, comptime as: @Type(.enum_literal)) if (as == .js) *JSC.EventLoop else *MiniEventLoop { if (as == .js) { if (this != .js) @panic("Expected *JSC.EventLoop but got *MiniEventLoop"); return this.js; @@ -2236,7 +2306,7 @@ pub const EventLoopHandle = union(enum) { pub fn init(context: anytype) EventLoopHandle { const Context = @TypeOf(context); return switch (Context) { - *JSC.VirtualMachine => .{ .js = context.eventLoop() }, + *VirtualMachine => .{ .js = context.eventLoop() }, *JSC.EventLoop => .{ .js = context }, *JSC.MiniEventLoop => .{ .mini = context }, *AnyEventLoop => switch (context.*) { @@ -2297,7 +2367,7 @@ pub const EventLoopHandle = union(enum) { this.loop().unref(); } - pub inline fn createNullDelimitedEnvMap(this: @This(), alloc: Allocator) ![:null]?[*:0]u8 { + pub inline fn createNullDelimitedEnvMap(this: @This(), alloc: Allocator) ![:null]?[*:0]const u8 { return switch (this) { .js => this.js.virtual_machine.transpiler.env.map.createNullDelimitedEnvMap(alloc), .mini => this.mini.env.?.map.createNullDelimitedEnvMap(alloc), @@ -2330,7 +2400,7 @@ pub const EventLoopTask = union { js: ConcurrentTask, mini: JSC.AnyTaskWithExtraContext, - pub fn init(comptime kind: @TypeOf(.EnumLiteral)) EventLoopTask { + pub fn init(comptime kind: @TypeOf(.enum_literal)) EventLoopTask { switch (kind) { .js => return .{ .js = ConcurrentTask{} }, .mini => return .{ .mini = JSC.AnyTaskWithExtraContext{} }, @@ -2390,7 +2460,7 @@ pub const PosixSignalHandle = struct { // Publish the new tail (Release so that the consumer sees the updated tail). this.tail.store(old_tail +% 1, .release); - JSC.VirtualMachine.getMainThreadVM().?.eventLoop().wakeup(); + VirtualMachine.getMainThreadVM().?.eventLoop().wakeup(); return true; } @@ -2398,7 +2468,7 @@ pub const PosixSignalHandle = struct { /// This is the signal handler entry point. Calls enqueue on the ring buffer. /// Note: Must be minimal logic here. Only do atomics & signal‐safe calls. export fn Bun__onPosixSignal(number: i32) void { - const vm = JSC.VirtualMachine.getMainThreadVM().?; + const vm = VirtualMachine.getMainThreadVM().?; _ = vm.eventLoop().signal_handler.?.enqueue(@intCast(number)); } @@ -2439,7 +2509,7 @@ pub const PosixSignalHandle = struct { pub const PosixSignalTask = struct { number: u8, - extern "C" fn Bun__onSignalForJS(number: i32, globalObject: *JSC.JSGlobalObject) void; + extern "c" fn Bun__onSignalForJS(number: i32, globalObject: *JSC.JSGlobalObject) void; pub usingnamespace bun.New(@This()); pub fn runFromJSThread(number: u8, globalObject: *JSC.JSGlobalObject) void { diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index 83e93bd1335848..456bf943362691 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -695,8 +695,8 @@ fn NewSocketIPCHandler(comptime Context: type) type { // In the VirtualMachine case, `globalThis` is an optional, in case // the vm is freed before the socket closes. const globalThis = switch (@typeInfo(@TypeOf(this.globalThis))) { - .Pointer => this.globalThis, - .Optional => brk: { + .pointer => this.globalThis, + .optional => brk: { if (this.globalThis) |global| { break :brk global; } @@ -842,8 +842,8 @@ fn NewNamedPipeIPCHandler(comptime Context: type) type { bun.assert(bun.isSliceInBuffer(buffer, ipc.incoming.allocatedSlice())); const globalThis = switch (@typeInfo(@TypeOf(this.globalThis))) { - .Pointer => this.globalThis, - .Optional => brk: { + .pointer => this.globalThis, + .optional => brk: { if (this.globalThis) |global| { break :brk global; } diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 885af89e00bfc2..a5c975c2e9f40d 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false; const StaticExport = @import("./bindings/static_export.zig"); const bun = @import("root").bun; const string = bun.string; @@ -13,7 +12,6 @@ const default_allocator = bun.default_allocator; const StoredFileDescriptorType = bun.StoredFileDescriptorType; const ErrorableString = bun.JSC.ErrorableString; const Arena = @import("../allocators/mimalloc_arena.zig").Arena; -const C = bun.C; const Exception = bun.JSC.Exception; const Allocator = std.mem.Allocator; @@ -42,14 +40,7 @@ const ImportRecord = ast.ImportRecord; const DotEnv = @import("../env_loader.zig"); const PackageJSON = @import("../resolver/package_json.zig").PackageJSON; const MacroRemap = @import("../resolver/package_json.zig").MacroMap; -const WebCore = bun.JSC.WebCore; -const Request = WebCore.Request; -const Response = WebCore.Response; -const Headers = WebCore.Headers; const String = bun.String; -const Fetch = WebCore.Fetch; -const FetchEvent = WebCore.FetchEvent; -const js = bun.JSC.C; const JSC = bun.JSC; const JSError = @import("./base.zig").JSError; const d = @import("./base.zig").d; @@ -67,18 +58,17 @@ const ZigException = bun.JSC.ZigException; const ZigStackTrace = bun.JSC.ZigStackTrace; const ErrorableResolvedSource = bun.JSC.ErrorableResolvedSource; const ResolvedSource = bun.JSC.ResolvedSource; -const JSPromise = bun.JSC.JSPromise; const JSInternalPromise = bun.JSC.JSInternalPromise; const JSModuleLoader = bun.JSC.JSModuleLoader; const JSPromiseRejectionOperation = bun.JSC.JSPromiseRejectionOperation; const ErrorableZigString = bun.JSC.ErrorableZigString; const ZigGlobalObject = bun.JSC.ZigGlobalObject; -const VM = bun.JSC.VM; +const VM = JSC.VM; const JSFunction = bun.JSC.JSFunction; const Config = @import("./config.zig"); const URL = @import("../url.zig").URL; const Bun = JSC.API.Bun; -const EventLoop = JSC.EventLoop; +const EventLoop = bun.JSC.EventLoop; const PendingResolution = @import("../resolver/resolver.zig").PendingResolution; const ThreadSafeFunction = JSC.napi.ThreadSafeFunction; const PackageManager = @import("../install/install.zig").PackageManager; @@ -94,8 +84,6 @@ const Task = JSC.Task; pub const Buffer = MarkedArrayBuffer; const Lock = bun.Mutex; -const BuildMessage = JSC.BuildMessage; -const ResolveMessage = JSC.ResolveMessage; const Async = bun.Async; const Ordinal = bun.Ordinal; @@ -322,13 +310,13 @@ pub const SavedSourceMap = struct { }; switch (Value.from(mapping.value_ptr.*).tag()) { - Value.Tag.ParsedSourceMap => { + @field(Value.Tag, @typeName(ParsedSourceMap)) => { defer this.unlock(); const map = Value.from(mapping.value_ptr.*).as(ParsedSourceMap); map.ref(); return .{ .map = map }; }, - Value.Tag.SavedMappings => { + @field(Value.Tag, @typeName(SavedMappings)) => { defer this.unlock(); var saved = SavedMappings{ .data = @as([*]u8, @ptrCast(Value.from(mapping.value_ptr.*).as(ParsedSourceMap))) }; defer saved.deinit(); @@ -341,7 +329,7 @@ pub const SavedSourceMap = struct { return .{ .map = result }; }, - Value.Tag.SourceProviderMap => { + @field(Value.Tag, @typeName(SourceProviderMap)) => { const ptr: *SourceProviderMap = Value.from(mapping.value_ptr.*).as(SourceProviderMap); this.unlock(); @@ -424,17 +412,17 @@ export fn Bun__readOriginTimerStart(vm: *JSC.VirtualMachine) f64 { return @as(f64, @floatCast((@as(f64, @floatFromInt(vm.origin_timestamp)) + JSC.VirtualMachine.origin_relative_epoch) / 1_000_000.0)); } -pub export fn Bun__GlobalObject__hasIPC(global: *JSC.JSGlobalObject) bool { +pub export fn Bun__GlobalObject__hasIPC(global: *JSGlobalObject) bool { return global.bunVM().ipc != null; } -extern fn Bun__Process__queueNextTick1(*JSC.ZigGlobalObject, JSC.JSValue, JSC.JSValue) void; +extern fn Bun__Process__queueNextTick1(*ZigGlobalObject, JSValue, JSValue) void; comptime { const Bun__Process__send = JSC.toJSHostFunction(Bun__Process__send_); - @export(Bun__Process__send, .{ .name = "Bun__Process__send" }); + @export(&Bun__Process__send, .{ .name = "Bun__Process__send" }); } -pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSC.JSValue { +pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSValue { JSC.markBinding(@src()); var message, var handle, var options_, var callback = callFrame.argumentsAsArray(4); @@ -450,7 +438,7 @@ pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFr } const S = struct { - fn impl(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { + fn impl(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue { const arguments_ = callframe.arguments_old(1).slice(); const ex = arguments_[0]; VirtualMachine.Process__emitErrorEvent(globalThis, ex); @@ -459,13 +447,13 @@ pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFr }; const vm = globalObject.bunVM(); - const zigGlobal: *JSC.ZigGlobalObject = @ptrCast(globalObject); + const zigGlobal: *ZigGlobalObject = @ptrCast(globalObject); const ipc_instance = vm.getIPCInstance() orelse { const ex = globalObject.ERR_IPC_CHANNEL_CLOSED("Channel closed.", .{}).toJS(); if (callback.isFunction()) { Bun__Process__queueNextTick1(zigGlobal, callback, ex); } else { - const fnvalue = JSC.JSFunction.create(globalObject, "", S.impl, 1, .{}); + const fnvalue = JSFunction.create(globalObject, "", S.impl, 1, .{}); Bun__Process__queueNextTick1(zigGlobal, fnvalue, ex); } return .false; @@ -490,7 +478,7 @@ pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFr if (callback.isFunction()) { Bun__Process__queueNextTick1(zigGlobal, callback, ex); } else { - const fnvalue = JSC.JSFunction.create(globalObject, "", S.impl, 1, .{}); + const fnvalue = JSFunction.create(globalObject, "", S.impl, 1, .{}); Bun__Process__queueNextTick1(zigGlobal, fnvalue, ex); } } @@ -579,7 +567,7 @@ const WindowsOnly = struct { comptime { if (Environment.isWindows) { - @export(WindowsOnly.Bun__ZigGlobalObject__uvLoop, .{ .name = "Bun__ZigGlobalObject__uvLoop" }); + @export(&WindowsOnly.Bun__ZigGlobalObject__uvLoop, .{ .name = "Bun__ZigGlobalObject__uvLoop" }); } } @@ -594,8 +582,8 @@ pub const ExitHandler = struct { vm.exit_handler.exit_code = code; } - extern fn Process__dispatchOnBeforeExit(*JSC.JSGlobalObject, code: u8) void; - extern fn Process__dispatchOnExit(*JSC.JSGlobalObject, code: u8) void; + extern fn Process__dispatchOnBeforeExit(*JSGlobalObject, code: u8) void; + extern fn Process__dispatchOnExit(*JSGlobalObject, code: u8) void; extern fn Bun__closeAllSQLiteDatabasesForTermination() void; pub fn dispatchOnExit(this: *ExitHandler) void { @@ -778,23 +766,24 @@ pub const VirtualMachine = struct { console: *ConsoleObject, log: *logger.Log, main: string = "", + main_is_html_entrypoint: bool = false, main_resolved_path: bun.String = bun.String.empty, main_hash: u32 = 0, - process: js.JSObjectRef = null, + process: bun.JSC.C.JSObjectRef = null, entry_point: ServerEntryPoint = undefined, origin: URL = URL{}, node_fs: ?*Node.NodeFS = null, - timer: Bun.Timer.All = .{}, + timer: Bun.Timer.All, event_loop_handle: ?*PlatformEventLoop = null, pending_unref_counter: i32 = 0, preload: []const string = &[_][]const u8{}, - unhandled_pending_rejection_to_capture: ?*JSC.JSValue = null, + unhandled_pending_rejection_to_capture: ?*JSValue = null, standalone_module_graph: ?*bun.StandaloneModuleGraph = null, smol: bool = false, dns_result_order: DNSResolver.Order = .verbatim, hot_reload: bun.CLI.Command.HotReload = .none, - jsc: *JSC.VM = undefined, + jsc: *VM = undefined, /// hide bun:wrap from stack traces /// bun:wrap is very noisy @@ -874,7 +863,7 @@ pub const VirtualMachine = struct { rare_data: ?*JSC.RareData = null, is_us_loop_entered: bool = false, - pending_internal_promise: *JSC.JSInternalPromise = undefined, + pending_internal_promise: *JSInternalPromise = undefined, entry_point_result: struct { value: JSC.Strong = .{}, cjs_set_value: bool = false, @@ -906,7 +895,9 @@ pub const VirtualMachine = struct { body_value_hive_allocator: BodyValueHiveAllocator = undefined, - pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSC.JSGlobalObject, JSC.JSValue) void; + is_inside_deferred_task_queue: bool = false, + + pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSGlobalObject, JSValue) void; pub const OnException = fn (*ZigException) void; @@ -914,6 +905,8 @@ pub const VirtualMachine = struct { return BodyValueRef.init(body, &this.body_value_hive_allocator); } + pub threadlocal var is_bundler_thread_for_bytecode_cache: bool = false; + pub fn uwsLoop(this: *const VirtualMachine) *uws.Loop { if (comptime Environment.isPosix) { if (Environment.allow_assert) { @@ -1099,11 +1092,11 @@ pub const VirtualMachine = struct { } }; - pub fn onQuietUnhandledRejectionHandler(this: *VirtualMachine, _: *JSC.JSGlobalObject, _: JSC.JSValue) void { + pub fn onQuietUnhandledRejectionHandler(this: *VirtualMachine, _: *JSGlobalObject, _: JSValue) void { this.unhandled_error_counter += 1; } - pub fn onQuietUnhandledRejectionHandlerCaptureValue(this: *VirtualMachine, _: *JSC.JSGlobalObject, value: JSC.JSValue) void { + pub fn onQuietUnhandledRejectionHandlerCaptureValue(this: *VirtualMachine, _: *JSGlobalObject, value: JSValue) void { this.unhandled_error_counter += 1; value.ensureStillAlive(); if (this.unhandled_pending_rejection_to_capture) |ptr| { @@ -1189,15 +1182,15 @@ pub const VirtualMachine = struct { } } - extern fn Bun__handleUncaughtException(*JSC.JSGlobalObject, err: JSC.JSValue, is_rejection: c_int) c_int; - extern fn Bun__handleUnhandledRejection(*JSC.JSGlobalObject, reason: JSC.JSValue, promise: JSC.JSValue) c_int; - extern fn Bun__Process__exit(*JSC.JSGlobalObject, code: c_int) noreturn; + extern fn Bun__handleUncaughtException(*JSGlobalObject, err: JSValue, is_rejection: c_int) c_int; + extern fn Bun__handleUnhandledRejection(*JSGlobalObject, reason: JSValue, promise: JSValue) c_int; + extern fn Bun__Process__exit(*JSGlobalObject, code: c_int) noreturn; export fn Bun__VirtualMachine__exitDuringUncaughtException(this: *JSC.VirtualMachine) void { this.exit_on_uncaught_exception = true; } - pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSC.JSGlobalObject, reason: JSC.JSValue, promise: JSC.JSValue) bool { + pub fn unhandledRejection(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, reason: JSValue, promise: JSValue) bool { if (this.isShuttingDown()) { Output.debugWarn("unhandledRejection during shutdown.", .{}); return true; @@ -1217,7 +1210,7 @@ pub const VirtualMachine = struct { return handled; } - pub fn uncaughtException(this: *JSC.VirtualMachine, globalObject: *JSC.JSGlobalObject, err: JSC.JSValue, is_rejection: bool) bool { + pub fn uncaughtException(this: *JSC.VirtualMachine, globalObject: *JSGlobalObject, err: JSValue, is_rejection: bool) bool { if (this.isShuttingDown()) { Output.debugWarn("uncaughtException during shutdown.", .{}); return true; @@ -1258,7 +1251,7 @@ pub const VirtualMachine = struct { } } - pub fn defaultOnUnhandledRejection(this: *JSC.VirtualMachine, _: *JSC.JSGlobalObject, value: JSC.JSValue) void { + pub fn defaultOnUnhandledRejection(this: *JSC.VirtualMachine, _: *JSGlobalObject, value: JSValue) void { this.runErrorHandler(value, this.onUnhandledRejectionExceptionList); } @@ -1267,7 +1260,7 @@ pub const VirtualMachine = struct { } pub fn garbageCollect(this: *const VirtualMachine, sync: bool) usize { - @setCold(true); + @branchHint(.cold); Global.mimalloc_cleanup(false); if (sync) return this.global.vm().runGC(true); @@ -1402,10 +1395,10 @@ pub const VirtualMachine = struct { } comptime { - @export(scriptExecutionStatus, .{ .name = "Bun__VM__scriptExecutionStatus" }); - @export(setEntryPointEvalResultESM, .{ .name = "Bun__VM__setEntryPointEvalResultESM" }); - @export(setEntryPointEvalResultCJS, .{ .name = "Bun__VM__setEntryPointEvalResultCJS" }); - @export(specifierIsEvalEntryPoint, .{ .name = "Bun__VM__specifierIsEvalEntryPoint" }); + @export(&scriptExecutionStatus, .{ .name = "Bun__VM__scriptExecutionStatus" }); + @export(&setEntryPointEvalResultESM, .{ .name = "Bun__VM__setEntryPointEvalResultESM" }); + @export(&setEntryPointEvalResultCJS, .{ .name = "Bun__VM__setEntryPointEvalResultCJS" }); + @export(&specifierIsEvalEntryPoint, .{ .name = "Bun__VM__specifierIsEvalEntryPoint" }); } pub fn onExit(this: *VirtualMachine) void { @@ -1513,7 +1506,7 @@ pub const VirtualMachine = struct { pub const Handle = opaque { extern "c" fn Bun__LifecycleAgentReportReload(agent: *Handle) void; - extern "c" fn Bun__LifecycleAgentReportError(agent: *Handle, exception: *JSC.ZigException) void; + extern "c" fn Bun__LifecycleAgentReportError(agent: *Handle, exception: *ZigException) void; extern "c" fn Bun__LifecycleAgentPreventExit(agent: *Handle) void; extern "c" fn Bun__LifecycleAgentStopPreventingExit(agent: *Handle) void; @@ -1530,7 +1523,7 @@ pub const VirtualMachine = struct { Bun__LifecycleAgentReportReload(this); } - pub fn reportError(this: *Handle, exception: *JSC.ZigException) void { + pub fn reportError(this: *Handle, exception: *ZigException) void { debug("reportError", .{}); Bun__LifecycleAgentReportError(this, exception); } @@ -1557,7 +1550,7 @@ pub const VirtualMachine = struct { } } - pub fn reportError(this: *LifecycleAgent, exception: *JSC.ZigException) void { + pub fn reportError(this: *LifecycleAgent, exception: *ZigException) void { if (this.handle) |handle| { handle.reportError(exception); } @@ -1592,9 +1585,9 @@ pub const VirtualMachine = struct { pub const log = Output.scoped(.debugger, false); - extern "C" fn Bun__createJSDebugger(*JSC.JSGlobalObject) u32; - extern "C" fn Bun__ensureDebugger(u32, bool) void; - extern "C" fn Bun__startJSDebuggerThread(*JSC.JSGlobalObject, u32, *bun.String, c_int, bool) void; + extern "c" fn Bun__createJSDebugger(*JSGlobalObject) u32; + extern "c" fn Bun__ensureDebugger(u32, bool) void; + extern "c" fn Bun__startJSDebuggerThread(*JSGlobalObject, u32, *bun.String, c_int, bool) void; var futex_atomic: std.atomic.Value(u32) = undefined; pub fn waitForDebuggerIfNecessary(this: *VirtualMachine) void { @@ -1726,7 +1719,8 @@ pub const VirtualMachine = struct { vm.is_main_thread = false; vm.eventLoop().ensureWaker(); - vm.global.vm().holdAPILock(other_vm, @ptrCast(&start)); + const callback = OpaqueWrap(VirtualMachine, start); + vm.global.vm().holdAPILock(other_vm, callback); } pub export fn Debugger__didConnect() void { @@ -1823,7 +1817,7 @@ pub const VirtualMachine = struct { this.eventLoop().waitForTasks(); } - pub const MacroMap = std.AutoArrayHashMap(i32, js.JSObjectRef); + pub const MacroMap = std.AutoArrayHashMap(i32, bun.JSC.C.JSObjectRef); pub fn enableMacroMode(this: *VirtualMachine) void { JSC.markBinding(@src()); @@ -1906,6 +1900,7 @@ pub const VirtualMachine = struct { .transpiler = transpiler, .console = console, .log = log, + .timer = JSC.BunTimer.All.init(), .origin = transpiler.options.origin, .saved_source_map_table = SavedSourceMap.HashTable.init(bun.default_allocator), .source_mappings = undefined, @@ -1928,6 +1923,7 @@ pub const VirtualMachine = struct { vm.regular_event_loop.next_immediate_tasks = EventLoop.Queue.init( default_allocator, ); + vm.regular_event_loop.virtual_machine = vm; vm.regular_event_loop.tasks.ensureUnusedCapacity(64) catch unreachable; vm.regular_event_loop.concurrent_tasks = .{}; vm.event_loop = &vm.regular_event_loop; @@ -1939,7 +1935,7 @@ pub const VirtualMachine = struct { vm.transpiler.resolver.onWakePackageManager = .{ .context = &vm.modules, .handler = ModuleLoader.AsyncModule.Queue.onWakeHandler, - .onDependencyError = JSC.ModuleLoader.AsyncModule.Queue.onDependencyError, + .onDependencyError = ModuleLoader.AsyncModule.Queue.onDependencyError, }; vm.transpiler.resolver.standalone_module_graph = opts.graph.?; @@ -1952,6 +1948,7 @@ pub const VirtualMachine = struct { VMHolder.main_thread_vm = vm; } vm.global = ZigGlobalObject.create( + vm, vm.console, if (opts.is_main_thread) -1 else std.math.maxInt(i32), false, @@ -1959,8 +1956,8 @@ pub const VirtualMachine = struct { null, ); vm.regular_event_loop.global = vm.global; - vm.regular_event_loop.virtual_machine = vm; vm.jsc = vm.global.vm(); + uws.Loop.get().internal_loop_data.jsc_vm = vm.jsc; vm.configureDebugger(opts.debugger); vm.body_value_hive_allocator = BodyValueHiveAllocator.init(bun.typedAllocator(JSC.WebCore.Body.Value)); @@ -2023,7 +2020,11 @@ pub const VirtualMachine = struct { .transpiler = transpiler, .console = console, .log = log, + + .timer = JSC.BunTimer.All.init(), + .origin = transpiler.options.origin, + .saved_source_map_table = SavedSourceMap.HashTable.init(bun.default_allocator), .source_mappings = undefined, .macros = MacroMap.init(allocator), @@ -2044,6 +2045,7 @@ pub const VirtualMachine = struct { vm.regular_event_loop.next_immediate_tasks = EventLoop.Queue.init( default_allocator, ); + vm.regular_event_loop.virtual_machine = vm; vm.regular_event_loop.tasks.ensureUnusedCapacity(64) catch unreachable; vm.regular_event_loop.concurrent_tasks = .{}; vm.event_loop = &vm.regular_event_loop; @@ -2055,7 +2057,7 @@ pub const VirtualMachine = struct { vm.transpiler.resolver.onWakePackageManager = .{ .context = &vm.modules, .handler = ModuleLoader.AsyncModule.Queue.onWakeHandler, - .onDependencyError = JSC.ModuleLoader.AsyncModule.Queue.onDependencyError, + .onDependencyError = ModuleLoader.AsyncModule.Queue.onDependencyError, }; vm.transpiler.configureLinker(); @@ -2063,6 +2065,7 @@ pub const VirtualMachine = struct { vm.transpiler.macro_context = js_ast.Macro.MacroContext.init(&vm.transpiler); vm.global = ZigGlobalObject.create( + vm, vm.console, if (opts.is_main_thread) -1 else std.math.maxInt(i32), opts.smol, @@ -2070,8 +2073,8 @@ pub const VirtualMachine = struct { null, ); vm.regular_event_loop.global = vm.global; - vm.regular_event_loop.virtual_machine = vm; vm.jsc = vm.global.vm(); + uws.Loop.get().internal_loop_data.jsc_vm = vm.jsc; vm.smol = opts.smol; vm.dns_result_order = opts.dns_result_order; @@ -2177,7 +2180,10 @@ pub const VirtualMachine = struct { .transpiler = transpiler, .console = console, .log = log, + + .timer = JSC.BunTimer.All.init(), .origin = transpiler.options.origin, + .saved_source_map_table = SavedSourceMap.HashTable.init(bun.default_allocator), .source_mappings = undefined, .macros = MacroMap.init(allocator), @@ -2200,6 +2206,7 @@ pub const VirtualMachine = struct { vm.regular_event_loop.next_immediate_tasks = EventLoop.Queue.init( default_allocator, ); + vm.regular_event_loop.virtual_machine = vm; vm.regular_event_loop.tasks.ensureUnusedCapacity(64) catch unreachable; vm.regular_event_loop.concurrent_tasks = .{}; vm.event_loop = &vm.regular_event_loop; @@ -2210,7 +2217,7 @@ pub const VirtualMachine = struct { vm.transpiler.resolver.onWakePackageManager = .{ .context = &vm.modules, .handler = ModuleLoader.AsyncModule.Queue.onWakeHandler, - .onDependencyError = JSC.ModuleLoader.AsyncModule.Queue.onDependencyError, + .onDependencyError = ModuleLoader.AsyncModule.Queue.onDependencyError, }; vm.transpiler.resolver.standalone_module_graph = opts.graph; @@ -2224,6 +2231,7 @@ pub const VirtualMachine = struct { vm.transpiler.macro_context = js_ast.Macro.MacroContext.init(&vm.transpiler); vm.global = ZigGlobalObject.create( + vm, vm.console, @as(i32, @intCast(worker.execution_context_id)), worker.mini, @@ -2231,8 +2239,8 @@ pub const VirtualMachine = struct { worker.cpp_worker, ); vm.regular_event_loop.global = vm.global; - vm.regular_event_loop.virtual_machine = vm; vm.jsc = vm.global.vm(); + uws.Loop.get().internal_loop_data.jsc_vm = vm.jsc; vm.transpiler.setAllocator(allocator); vm.body_value_hive_allocator = BodyValueHiveAllocator.init(bun.typedAllocator(JSC.WebCore.Body.Value)); @@ -2269,6 +2277,7 @@ pub const VirtualMachine = struct { .transpiler = transpiler, .console = console, .log = log, + .timer = JSC.BunTimer.All.init(), .origin = transpiler.options.origin, .saved_source_map_table = SavedSourceMap.HashTable.init(bun.default_allocator), .source_mappings = undefined, @@ -2290,9 +2299,11 @@ pub const VirtualMachine = struct { vm.regular_event_loop.next_immediate_tasks = EventLoop.Queue.init( default_allocator, ); + vm.regular_event_loop.virtual_machine = vm; vm.regular_event_loop.tasks.ensureUnusedCapacity(64) catch unreachable; vm.regular_event_loop.concurrent_tasks = .{}; vm.event_loop = &vm.regular_event_loop; + vm.eventLoop().ensureWaker(); vm.transpiler.macro_context = null; vm.transpiler.resolver.store_fd = opts.store_fd; @@ -2301,14 +2312,13 @@ pub const VirtualMachine = struct { vm.transpiler.resolver.onWakePackageManager = .{ .context = &vm.modules, .handler = ModuleLoader.AsyncModule.Queue.onWakeHandler, - .onDependencyError = JSC.ModuleLoader.AsyncModule.Queue.onDependencyError, + .onDependencyError = ModuleLoader.AsyncModule.Queue.onDependencyError, }; vm.transpiler.configureLinker(); vm.transpiler.macro_context = js_ast.Macro.MacroContext.init(&vm.transpiler); - vm.regular_event_loop.virtual_machine = vm; vm.smol = opts.smol; if (opts.smol) @@ -2392,7 +2402,7 @@ pub const VirtualMachine = struct { pub fn fetchWithoutOnLoadPlugins( jsc_vm: *VirtualMachine, - globalObject: *JSC.JSGlobalObject, + globalObject: *JSGlobalObject, _specifier: String, referrer: String, log: *logger.Log, @@ -2709,7 +2719,7 @@ pub const VirtualMachine = struct { defer specifier_utf8.deinit(); const source_utf8 = source.toUTF8(bun.default_allocator); defer source_utf8.deinit(); - const printed = ResolveMessage.fmt( + const printed = JSC.ResolveMessage.fmt( bun.default_allocator, specifier_utf8.slice(), source_utf8.slice(), @@ -2722,7 +2732,7 @@ pub const VirtualMachine = struct { printed, ), }; - res.* = ErrorableString.err(error.NameTooLong, ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice()).asVoid()); + res.* = ErrorableString.err(error.NameTooLong, JSC.ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice()).asVoid()); return; } @@ -2790,7 +2800,7 @@ pub const VirtualMachine = struct { } } - const printed = ResolveMessage.fmt( + const printed = JSC.ResolveMessage.fmt( jsc_vm.allocator, specifier_utf8.slice(), source_utf8.slice(), @@ -2810,7 +2820,7 @@ pub const VirtualMachine = struct { }; { - res.* = ErrorableString.err(err, ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice()).asVoid()); + res.* = ErrorableString.err(err, JSC.ResolveMessage.create(global, VirtualMachine.get().allocator, msg, source_utf8.slice()).asVoid()); } return; @@ -2848,7 +2858,7 @@ pub const VirtualMachine = struct { }; }; { - ret.* = ErrorableResolvedSource.err(err, BuildMessage.create(globalThis, globalThis.allocator(), msg).asVoid()); + ret.* = ErrorableResolvedSource.err(err, JSC.BuildMessage.create(globalThis, globalThis.allocator(), msg).asVoid()); } return; }, @@ -2856,8 +2866,8 @@ pub const VirtualMachine = struct { 1 => { const msg = log.msgs.items[0]; ret.* = ErrorableResolvedSource.err(err, switch (msg.metadata) { - .build => BuildMessage.create(globalThis, globalThis.allocator(), msg).asVoid(), - .resolve => ResolveMessage.create( + .build => JSC.BuildMessage.create(globalThis, globalThis.allocator(), msg).asVoid(), + .resolve => JSC.ResolveMessage.create( globalThis, globalThis.allocator(), msg, @@ -2875,8 +2885,8 @@ pub const VirtualMachine = struct { for (logs, errors) |msg, *current| { current.* = switch (msg.metadata) { - .build => BuildMessage.create(globalThis, globalThis.allocator(), msg), - .resolve => ResolveMessage.create( + .build => JSC.BuildMessage.create(globalThis, globalThis.allocator(), msg), + .resolve => JSC.ResolveMessage.create( globalThis, globalThis.allocator(), msg, @@ -2948,7 +2958,7 @@ pub const VirtualMachine = struct { } pub noinline fn runErrorHandler(this: *VirtualMachine, result: JSValue, exception_list: ?*ExceptionList) void { - @setCold(true); + @branchHint(.cold); if (!result.isEmptyOrUndefinedOrNull()) this.last_reported_error_for_dedupe = result; @@ -2988,7 +2998,7 @@ pub const VirtualMachine = struct { } } - export fn Bun__logUnhandledException(exception: JSC.JSValue) void { + export fn Bun__logUnhandledException(exception: JSValue) void { get().runErrorHandler(exception, null); } @@ -3089,6 +3099,8 @@ pub const VirtualMachine = struct { } } + extern fn Bun__loadHTMLEntryPoint(global: *JSGlobalObject) *JSInternalPromise; + pub fn reloadEntryPoint(this: *VirtualMachine, entry_path: []const u8) !*JSInternalPromise { this.has_loaded = false; this.main = entry_path; @@ -3096,30 +3108,35 @@ pub const VirtualMachine = struct { try this.ensureDebugger(true); - try this.entry_point.generate( - this.allocator, - this.bun_watcher != .none, - entry_path, - main_file_name, - ); - this.eventLoop().ensureWaker(); + if (!this.main_is_html_entrypoint) { + try this.entry_point.generate( + this.allocator, + this.bun_watcher != .none, + entry_path, + main_file_name, + ); + } if (!this.transpiler.options.disable_transpilation) { if (try this.loadPreloads()) |promise| { - JSC.JSValue.fromCell(promise).ensureStillAlive(); - JSC.JSValue.fromCell(promise).protect(); + JSValue.fromCell(promise).ensureStillAlive(); + JSValue.fromCell(promise).protect(); this.pending_internal_promise = promise; return promise; } - const promise = JSModuleLoader.loadAndEvaluateModule(this.global, &String.init(main_file_name)) orelse return error.JSError; + const promise = if (!this.main_is_html_entrypoint) + JSModuleLoader.loadAndEvaluateModule(this.global, &String.init(main_file_name)) orelse return error.JSError + else + Bun__loadHTMLEntryPoint(this.global); + this.pending_internal_promise = promise; - JSC.JSValue.fromCell(promise).ensureStillAlive(); + JSValue.fromCell(promise).ensureStillAlive(); return promise; } else { const promise = JSModuleLoader.loadAndEvaluateModule(this.global, &String.fromBytes(this.main)) orelse return error.JSError; this.pending_internal_promise = promise; - JSC.JSValue.fromCell(promise).ensureStillAlive(); + JSValue.fromCell(promise).ensureStillAlive(); return promise; } @@ -3136,9 +3153,9 @@ pub const VirtualMachine = struct { if (!this.transpiler.options.disable_transpilation) { if (try this.loadPreloads()) |promise| { - JSC.JSValue.fromCell(promise).ensureStillAlive(); + JSValue.fromCell(promise).ensureStillAlive(); this.pending_internal_promise = promise; - JSC.JSValue.fromCell(promise).protect(); + JSValue.fromCell(promise).protect(); return promise; } @@ -3146,7 +3163,7 @@ pub const VirtualMachine = struct { const promise = JSModuleLoader.loadAndEvaluateModule(this.global, &String.fromBytes(this.main)) orelse return error.JSError; this.pending_internal_promise = promise; - JSC.JSValue.fromCell(promise).ensureStillAlive(); + JSValue.fromCell(promise).ensureStillAlive(); return promise; } @@ -3311,10 +3328,6 @@ pub const VirtualMachine = struct { comptime allow_ansi_color: bool, comptime allow_side_effects: bool, ) void { - if (comptime JSC.is_bindgen) { - return; - } - var was_internal = false; defer { @@ -3378,7 +3391,7 @@ pub const VirtualMachine = struct { fn printErrorFromMaybePrivateData( this: *VirtualMachine, - value: JSC.JSValue, + value: JSValue, exception_list: ?*ExceptionList, formatter: *ConsoleObject.Formatter, comptime Writer: type, @@ -3447,7 +3460,7 @@ pub const VirtualMachine = struct { return false; } - pub fn reportUncaughtException(globalObject: *JSGlobalObject, exception: *JSC.Exception) JSValue { + pub fn reportUncaughtException(globalObject: *JSGlobalObject, exception: *Exception) JSValue { var jsc_vm = globalObject.bunVM(); _ = jsc_vm.uncaughtException(globalObject, exception.value(), false); return .undefined; @@ -3538,7 +3551,7 @@ pub const VirtualMachine = struct { } } - pub export fn Bun__remapStackFramePositions(globalObject: *JSC.JSGlobalObject, frames: [*]JSC.ZigStackFrame, frames_count: usize) void { + pub export fn Bun__remapStackFramePositions(globalObject: *JSGlobalObject, frames: [*]JSC.ZigStackFrame, frames_count: usize) void { globalObject.bunVM().remapStackFramePositions(frames, frames_count); } @@ -3749,11 +3762,11 @@ pub const VirtualMachine = struct { if (strings.getLinesInText( code.slice(), @intCast(last_line), - JSC.ZigException.Holder.source_lines_count, + ZigException.Holder.source_lines_count, )) |lines_buf| { var lines = lines_buf.slice(); - var source_lines = exception.stack.source_lines_ptr[0..JSC.ZigException.Holder.source_lines_count]; - var source_line_numbers = exception.stack.source_lines_numbers[0..JSC.ZigException.Holder.source_lines_count]; + var source_lines = exception.stack.source_lines_ptr[0..ZigException.Holder.source_lines_count]; + var source_line_numbers = exception.stack.source_lines_numbers[0..ZigException.Holder.source_lines_count]; @memset(source_lines, String.empty); @memset(source_line_numbers, 0); @@ -3992,7 +4005,7 @@ pub const VirtualMachine = struct { } // This is usually unsafe to do, but we are protecting them each time first - var errors_to_append = std.ArrayList(JSC.JSValue).init(this.allocator); + var errors_to_append = std.ArrayList(JSValue).init(this.allocator); defer { for (errors_to_append.items) |err| { err.unprotect(); @@ -4196,8 +4209,8 @@ pub const VirtualMachine = struct { // In Github Actions, emit an annotation that renders the error and location. // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message - pub noinline fn printGithubAnnotation(exception: *JSC.ZigException) void { - @setCold(true); + pub noinline fn printGithubAnnotation(exception: *ZigException) void { + @branchHint(.cold); const name = exception.name; const message = exception.message; const frames = exception.stack.frames(); @@ -4422,7 +4435,7 @@ pub const VirtualMachine = struct { this.destroy(); } - extern fn Bun__setChannelRef(*JSC.JSGlobalObject, bool) void; + extern fn Bun__setChannelRef(*JSGlobalObject, bool) void; export fn Bun__closeChildIPC(global: *JSGlobalObject) void { if (global.bunVM().ipc) |*current_ipc| { @@ -4518,8 +4531,8 @@ pub const VirtualMachine = struct { } }; -pub const HotReloader = NewHotReloader(VirtualMachine, JSC.EventLoop, false); -pub const WatchReloader = NewHotReloader(VirtualMachine, JSC.EventLoop, true); +pub const HotReloader = NewHotReloader(VirtualMachine, EventLoop, false); +pub const WatchReloader = NewHotReloader(VirtualMachine, EventLoop, true); extern fn BunDebugger__willHotReload() void; pub fn NewHotReloader(comptime Ctx: type, comptime EventLoopType: type, comptime reload_immediately: bool) type { @@ -4736,7 +4749,7 @@ pub fn NewHotReloader(comptime Ctx: type, comptime EventLoopType: type, comptime } else { return this.ctx.bun_watcher.hot; } - } else if (@typeInfo(@TypeOf(this.ctx.bun_watcher)) == .Optional) { + } else if (@typeInfo(@TypeOf(this.ctx.bun_watcher)) == .optional) { return this.ctx.bun_watcher.?; } else { return this.ctx.bun_watcher; @@ -4949,11 +4962,10 @@ pub var synthetic_allocation_limit: usize = std.math.maxInt(u32); pub var string_allocation_limit: usize = std.math.maxInt(u32); comptime { - @export(synthetic_allocation_limit, .{ .name = "Bun__syntheticAllocationLimit" }); - @export(string_allocation_limit, .{ .name = "Bun__stringSyntheticAllocationLimit" }); + @export(&string_allocation_limit, .{ .name = "Bun__stringSyntheticAllocationLimit" }); } -pub fn Bun__setSyntheticAllocationLimitForTesting(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue { +pub fn Bun__setSyntheticAllocationLimitForTesting(globalObject: *JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue { const args = callframe.arguments_old(1).slice(); if (args.len < 1) { return globalObject.throwNotEnoughArguments("setSyntheticAllocationLimitForTesting", 1, args.len); diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index 146ed7e35b3763..240e64ee2c36b7 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false; const StaticExport = @import("./bindings/static_export.zig"); const bun = @import("root").bun; const string = bun.string; @@ -40,12 +39,6 @@ const ImportRecord = ast.ImportRecord; const DotEnv = @import("../env_loader.zig"); const PackageJSON = @import("../resolver/package_json.zig").PackageJSON; const MacroRemap = @import("../resolver/package_json.zig").MacroMap; -const WebCore = bun.JSC.WebCore; -const Request = WebCore.Request; -const Response = WebCore.Response; -const Headers = WebCore.Headers; -const Fetch = WebCore.Fetch; -const FetchEvent = WebCore.FetchEvent; const js = bun.JSC.C; const JSC = bun.JSC; const JSError = @import("./base.zig").JSError; @@ -59,13 +52,10 @@ const JSGlobalObject = bun.JSC.JSGlobalObject; const ExceptionValueRef = bun.JSC.ExceptionValueRef; const JSPrivateDataPtr = bun.JSC.JSPrivateDataPtr; const ConsoleObject = bun.JSC.ConsoleObject; -const Node = bun.JSC.Node; const ZigException = bun.JSC.ZigException; const ZigStackTrace = bun.JSC.ZigStackTrace; -const ErrorableResolvedSource = bun.JSC.ErrorableResolvedSource; const ResolvedSource = bun.JSC.ResolvedSource; const JSPromise = bun.JSC.JSPromise; -const JSInternalPromise = bun.JSC.JSInternalPromise; const JSModuleLoader = bun.JSC.JSModuleLoader; const JSPromiseRejectionOperation = bun.JSC.JSPromiseRejectionOperation; const ErrorableZigString = bun.JSC.ErrorableZigString; @@ -80,7 +70,7 @@ const PendingResolution = @import("../resolver/resolver.zig").PendingResolution; const ThreadSafeFunction = JSC.napi.ThreadSafeFunction; const PackageManager = @import("../install/install.zig").PackageManager; const Install = @import("../install/install.zig"); -const VirtualMachine = JSC.VirtualMachine; +const VirtualMachine = bun.JSC.VirtualMachine; const Dependency = @import("../install/dependency.zig"); const Async = bun.Async; const String = bun.String; @@ -232,7 +222,7 @@ pub const RuntimeTranspilerStore = struct { } else { return; } - var vm: *JSC.VirtualMachine = @fieldParentPtr("transpiler_store", this); + var vm: *VirtualMachine = @fieldParentPtr("transpiler_store", this); const event_loop = vm.eventLoop(); const global = vm.global; const jsc_vm = vm.jsc; @@ -247,8 +237,8 @@ pub const RuntimeTranspilerStore = struct { pub fn transpile( this: *RuntimeTranspilerStore, - vm: *JSC.VirtualMachine, - globalObject: *JSC.JSGlobalObject, + vm: *VirtualMachine, + globalObject: *JSGlobalObject, input_specifier: bun.String, path: Fs.Path, referrer: bun.String, @@ -264,7 +254,7 @@ pub const RuntimeTranspilerStore = struct { .vm = vm, .log = logger.Log.init(bun.default_allocator), .loader = vm.transpiler.options.loader(owned_path.name.ext), - .promise = JSC.Strong.create(JSC.JSValue.fromCell(promise), globalObject), + .promise = JSC.Strong.create(JSValue.fromCell(promise), globalObject), .poll_ref = .{}, .fetcher = TranspilerJob.Fetcher{ .file = {}, @@ -282,8 +272,8 @@ pub const RuntimeTranspilerStore = struct { non_threadsafe_referrer: String, loader: options.Loader, promise: JSC.Strong = .{}, - vm: *JSC.VirtualMachine, - globalThis: *JSC.JSGlobalObject, + vm: *VirtualMachine, + globalThis: *JSGlobalObject, fetcher: Fetcher, poll_ref: Async.KeepAlive = .{}, generation_number: u32 = 0, @@ -714,7 +704,7 @@ pub const ModuleLoader = struct { } } - pub fn resolveEmbeddedFile(vm: *JSC.VirtualMachine, input_path: []const u8, extname: []const u8) ?[]const u8 { + pub fn resolveEmbeddedFile(vm: *VirtualMachine, input_path: []const u8, extname: []const u8) ?[]const u8 { if (input_path.len == 0) return null; var graph = vm.standalone_module_graph orelse return null; const file = graph.find(input_path) orelse return null; @@ -740,7 +730,7 @@ pub const ModuleLoader = struct { .{ .data = .{ - .encoded_slice = JSC.ZigString.Slice.fromUTF8NeverFree(file.contents), + .encoded_slice = ZigString.Slice.fromUTF8NeverFree(file.contents), }, .dirfd = bun.toFD(tmpdir.fd), .file = .{ @@ -770,7 +760,7 @@ pub const ModuleLoader = struct { package_json: ?*PackageJSON = null, loader: Api.Loader, hash: u32 = std.math.maxInt(u32), - globalThis: *JSC.JSGlobalObject = undefined, + globalThis: *JSGlobalObject = undefined, arena: *bun.ArenaAllocator, // This is the specific state for making it async @@ -806,7 +796,7 @@ pub const ModuleLoader = struct { pub const Map = std.ArrayListUnmanaged(AsyncModule); - pub fn enqueue(this: *Queue, globalObject: *JSC.JSGlobalObject, opts: anytype) void { + pub fn enqueue(this: *Queue, globalObject: *JSGlobalObject, opts: anytype) void { debug("enqueue: {s}", .{opts.specifier}); var module = AsyncModule.init(opts, globalObject) catch unreachable; module.poll_ref.ref(this.vm()); @@ -1064,7 +1054,7 @@ pub const ModuleLoader = struct { } }; - pub fn init(opts: anytype, globalObject: *JSC.JSGlobalObject) !AsyncModule { + pub fn init(opts: anytype, globalObject: *JSGlobalObject) !AsyncModule { var promise = JSC.Strong{}; // var stmt_blocks = js_ast.Stmt.Data.toOwnedSlice(); // var expr_blocks = js_ast.Expr.Data.toOwnedSlice(); @@ -1099,7 +1089,7 @@ pub const ModuleLoader = struct { }; } - pub fn done(this: *AsyncModule, jsc_vm: *JSC.VirtualMachine) void { + pub fn done(this: *AsyncModule, jsc_vm: *VirtualMachine) void { var clone = jsc_vm.allocator.create(AsyncModule) catch unreachable; clone.* = this.*; jsc_vm.modules.scheduled += 1; @@ -1116,11 +1106,11 @@ pub const ModuleLoader = struct { } var log = logger.Log.init(jsc_vm.allocator); defer log.deinit(); - var errorable: ErrorableResolvedSource = undefined; + var errorable: JSC.ErrorableResolvedSource = undefined; this.poll_ref.unref(jsc_vm); outer: { - errorable = ErrorableResolvedSource.ok(this.resumeLoadingModule(&log) catch |err| { - JSC.VirtualMachine.processFetchLog( + errorable = JSC.ErrorableResolvedSource.ok(this.resumeLoadingModule(&log) catch |err| { + VirtualMachine.processFetchLog( this.globalThis, bun.String.init(this.specifier), bun.String.init(this.referrer), @@ -1146,8 +1136,8 @@ pub const ModuleLoader = struct { } pub fn fulfill( - globalThis: *JSC.JSGlobalObject, - promise: JSC.JSValue, + globalThis: *JSGlobalObject, + promise: JSValue, resolved_source: ResolvedSource, err: ?anyerror, specifier_: bun.String, @@ -1162,9 +1152,9 @@ pub const ModuleLoader = struct { referrer.deref(); } - var errorable: ErrorableResolvedSource = undefined; + var errorable: JSC.ErrorableResolvedSource = undefined; if (err) |e| { - JSC.VirtualMachine.processFetchLog( + VirtualMachine.processFetchLog( globalThis, specifier, referrer, @@ -1173,7 +1163,7 @@ pub const ModuleLoader = struct { e, ); } else { - errorable = ErrorableResolvedSource.ok(resolved_source); + errorable = JSC.ErrorableResolvedSource.ok(resolved_source); } log.deinit(); @@ -1188,7 +1178,7 @@ pub const ModuleLoader = struct { ); } - pub fn resolveError(this: *AsyncModule, vm: *JSC.VirtualMachine, import_record_id: u32, result: PackageResolveError) !void { + pub fn resolveError(this: *AsyncModule, vm: *VirtualMachine, import_record_id: u32, result: PackageResolveError) !void { const globalThis = this.globalThis; const msg: []u8 = try switch (result.err) { @@ -1280,7 +1270,7 @@ pub const ModuleLoader = struct { this.deinit(); promise.rejectAsHandled(globalThis, error_instance); } - pub fn downloadError(this: *AsyncModule, vm: *JSC.VirtualMachine, import_record_id: u32, result: PackageDownloadError) !void { + pub fn downloadError(this: *AsyncModule, vm: *VirtualMachine, import_record_id: u32, result: PackageDownloadError) !void { const globalThis = this.globalThis; const msg_args = .{ @@ -1379,7 +1369,7 @@ pub const ModuleLoader = struct { debug("resumeLoadingModule: {s}", .{this.specifier}); var parse_result = this.parse_result; const path = this.path; - var jsc_vm = JSC.VirtualMachine.get(); + var jsc_vm = VirtualMachine.get(); const specifier = this.specifier; const old_log = jsc_vm.log; @@ -1469,16 +1459,16 @@ pub const ModuleLoader = struct { bun.default_allocator.free(this.string_buf); } - extern "C" fn Bun__onFulfillAsyncModule( - globalObject: *JSC.JSGlobalObject, - promiseValue: JSC.JSValue, + extern "c" fn Bun__onFulfillAsyncModule( + globalObject: *JSGlobalObject, + promiseValue: JSValue, res: *JSC.ErrorableResolvedSource, specifier: *bun.String, referrer: *bun.String, ) void; }; - pub export fn Bun__getDefaultLoader(global: *JSC.JSGlobalObject, str: *const bun.String) Api.Loader { + pub export fn Bun__getDefaultLoader(global: *JSGlobalObject, str: *const bun.String) Api.Loader { var jsc_vm = global.bunVM(); const filename = str.toUTF8(jsc_vm.allocator); defer filename.deinit(); @@ -1501,7 +1491,7 @@ pub const ModuleLoader = struct { virtual_source: ?*const logger.Source, promise_ptr: ?*?*JSC.JSInternalPromise, source_code_printer: *js_printer.BufferPrinter, - globalObject: ?*JSC.JSGlobalObject, + globalObject: ?*JSGlobalObject, comptime flags: FetchFlags, ) !ResolvedSource { const disable_transpilying = comptime flags.disableTranspiling(); @@ -1661,12 +1651,6 @@ pub const ModuleLoader = struct { var parse_result: ParseResult = switch (disable_transpilying or (loader == .json and !path.isJSONCFile())) { inline else => |return_file_only| brk: { - const heap_access = if (!disable_transpilying) - jsc_vm.jsc.releaseHeapAccess() - else - JSC.VM.ReleaseHeapAccess{ .vm = jsc_vm.jsc, .needs_to_release = false }; - defer heap_access.acquire(); - break :brk jsc_vm.transpiler.parseMaybeReturnFileOnly( parse_options, null, @@ -1771,7 +1755,7 @@ pub const ModuleLoader = struct { .specifier = input_specifier, .source_url = input_specifier.createIfDifferent(path.text), .hash = 0, - .jsvalue_for_export = JSC.JSValue.createEmptyObject(jsc_vm.global, 0), + .jsvalue_for_export = JSValue.createEmptyObject(jsc_vm.global, 0), .tag = .exports_object, }; } @@ -2014,10 +1998,10 @@ pub const ModuleLoader = struct { const encoded = JSC.EncodedJSValue{ .asPtr = globalThis, }; - const globalValue = @as(JSC.JSValue, @enumFromInt(encoded.asInt64)); + const globalValue = @as(JSValue, @enumFromInt(encoded.asInt64)); globalValue.put( globalThis, - JSC.ZigString.static("wasmSourceBytes"), + ZigString.static("wasmSourceBytes"), JSC.ArrayBuffer.create(globalThis, source.contents, .Uint8Array), ); } @@ -2232,10 +2216,10 @@ pub const ModuleLoader = struct { pub export fn Bun__fetchBuiltinModule( jsc_vm: *VirtualMachine, - globalObject: *JSC.JSGlobalObject, + globalObject: *JSGlobalObject, specifier: *bun.String, referrer: *bun.String, - ret: *ErrorableResolvedSource, + ret: *JSC.ErrorableResolvedSource, ) bool { JSC.markBinding(@src()); var log = logger.Log.init(jsc_vm.transpiler.allocator); @@ -2252,7 +2236,7 @@ pub const ModuleLoader = struct { VirtualMachine.processFetchLog(globalObject, specifier.*, referrer.*, &log, ret, err); return true; }) |builtin| { - ret.* = ErrorableResolvedSource.ok(builtin); + ret.* = JSC.ErrorableResolvedSource.ok(builtin); return true; } else { return false; @@ -2261,11 +2245,11 @@ pub const ModuleLoader = struct { pub export fn Bun__transpileFile( jsc_vm: *VirtualMachine, - globalObject: *JSC.JSGlobalObject, + globalObject: *JSGlobalObject, specifier_ptr: *bun.String, referrer: *bun.String, type_attribute: ?*const bun.String, - ret: *ErrorableResolvedSource, + ret: *JSC.ErrorableResolvedSource, allow_promise: bool, ) ?*anyopaque { JSC.markBinding(@src()); @@ -2333,7 +2317,7 @@ pub const ModuleLoader = struct { virtual_source = &virtual_source_to_use.?; } } else { - ret.* = ErrorableResolvedSource.err(error.JSErrorObject, globalObject.MODULE_NOT_FOUND("Blob not found", .{}).toJS().asVoid()); + ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.MODULE_NOT_FOUND("Blob not found", .{}).toJS().asVoid()); return null; } } @@ -2416,7 +2400,7 @@ pub const ModuleLoader = struct { defer jsc_vm.module_loader.resetArena(jsc_vm); var promise: ?*JSC.JSInternalPromise = null; - ret.* = ErrorableResolvedSource.ok( + ret.* = JSC.ErrorableResolvedSource.ok( ModuleLoader.transpileSourceCode( jsc_vm, specifier, @@ -2447,7 +2431,7 @@ pub const ModuleLoader = struct { return promise; } - export fn Bun__runVirtualModule(globalObject: *JSC.JSGlobalObject, specifier_ptr: *const bun.String) JSValue { + export fn Bun__runVirtualModule(globalObject: *JSGlobalObject, specifier_ptr: *const bun.String) JSValue { JSC.markBinding(@src()); if (globalObject.bunVM().plugin_runner == null) return JSValue.zero; @@ -2634,12 +2618,12 @@ pub const ModuleLoader = struct { } export fn Bun__transpileVirtualModule( - globalObject: *JSC.JSGlobalObject, + globalObject: *JSGlobalObject, specifier_ptr: *const bun.String, referrer_ptr: *const bun.String, source_code: *ZigString, loader_: Api.Loader, - ret: *ErrorableResolvedSource, + ret: *JSC.ErrorableResolvedSource, ) bool { JSC.markBinding(@src()); const jsc_vm = globalObject.bunVM(); @@ -2671,7 +2655,7 @@ pub const ModuleLoader = struct { defer log.deinit(); defer jsc_vm.module_loader.resetArena(jsc_vm); - ret.* = ErrorableResolvedSource.ok( + ret.* = JSC.ErrorableResolvedSource.ok( ModuleLoader.transpileSourceCode( jsc_vm, specifier_slice.slice(), @@ -3111,7 +3095,7 @@ pub const HardcodedModule = enum { }; /// Support embedded .node files -export fn Bun__resolveEmbeddedNodeFile(vm: *JSC.VirtualMachine, in_out_str: *bun.String) bool { +export fn Bun__resolveEmbeddedNodeFile(vm: *VirtualMachine, in_out_str: *bun.String) bool { if (vm.standalone_module_graph == null) return false; const input_path = in_out_str.toUTF8(bun.default_allocator); diff --git a/src/bun.js/modules/AbortControllerModuleModule.h b/src/bun.js/modules/AbortControllerModuleModule.h index 5a20e6b10cb065..3216a54f1af672 100644 --- a/src/bun.js/modules/AbortControllerModuleModule.h +++ b/src/bun.js/modules/AbortControllerModuleModule.h @@ -15,7 +15,7 @@ inline void generateNativeModule_AbortControllerModule( { Zig::GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* abortController = WebCore::JSAbortController::getConstructor(vm, globalObject).getObject(); JSValue abortSignal = WebCore::JSAbortSignal::getConstructor(vm, globalObject); diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index 562d795cfecea9..1246400d237436 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -68,7 +68,7 @@ JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger, static const char* defaultHost = "127.0.0.1\0"; static uint16_t defaultPort = 9230; // node + 1 - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue hostValue = callFrame->argument(0); @@ -117,7 +117,7 @@ JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger, RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::jsUndefined())); #else - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); throwVMError(globalObject, scope, createTypeError( @@ -215,7 +215,7 @@ JSC_DEFINE_HOST_FUNCTION(functionMemoryUsageStatistics, (JSGlobalObject * globalObject, CallFrame*)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); if (vm.heap.size() == 0) { vm.heap.collectNow(Sync, CollectionScope::Full); @@ -401,7 +401,7 @@ JSC_DEFINE_HOST_FUNCTION(functionStartSamplingProfiler, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create()); JSC::JSValue directoryValue = callFrame->argument(0); @@ -440,7 +440,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSamplingProfilerStackTraces, (JSC::JSGlobalObject * globalObject, JSC::CallFrame*)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::DeferTermination deferScope(vm); auto scope = DECLARE_THROW_SCOPE(vm); @@ -621,7 +621,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSetTimeZone, (JSGlobalObject * globalObject, Ca JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSC::SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(WTF::Stopwatch::create()); JSC::JSValue callbackValue = callFrame->argument(0); @@ -757,7 +757,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSerialize, CallFrame* callFrame)) { auto* globalObject = jsCast(lexicalGlobalObject); - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSValue value = callFrame->argument(0); @@ -813,7 +813,7 @@ JSC_DEFINE_HOST_FUNCTION(functionSerialize, } JSC_DEFINE_HOST_FUNCTION(functionDeserialize, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSValue value = callFrame->argument(0); @@ -895,7 +895,7 @@ JSC_DEFINE_HOST_FUNCTION(functionEstimateDirectMemoryUsageOf, (JSGlobalObject * auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); JSValue value = callFrame->argument(0); if (value.isCell()) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); EnsureStillAliveScope alive = value; return JSValue::encode(jsDoubleNumber(alive.value().asCell()->estimatedSizeInBytes(vm))); } diff --git a/src/bun.js/modules/BunObjectModule.cpp b/src/bun.js/modules/BunObjectModule.cpp deleted file mode 100644 index f0188456743da4..00000000000000 --- a/src/bun.js/modules/BunObjectModule.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "root.h" - -#include "ZigGlobalObject.h" - -#include "ObjectModule.h" - -namespace Zig { -void generateNativeModule_BunObject(JSC::JSGlobalObject* lexicalGlobalObject, - JSC::Identifier moduleKey, - Vector& exportNames, - JSC::MarkedArgumentBuffer& exportValues) -{ - // FIXME: this does not add each property as a top level export - JSC::VM& vm = lexicalGlobalObject->vm(); - Zig::GlobalObject* globalObject = jsCast(lexicalGlobalObject); - - JSObject* object = globalObject->bunObject(); - - exportNames.append(vm.propertyNames->defaultKeyword); - exportValues.append(object); -} - -} // namespace Zig diff --git a/src/bun.js/modules/BunTestModule.h b/src/bun.js/modules/BunTestModule.h index 4e276bd2fca5dc..a9f6334a25571c 100644 --- a/src/bun.js/modules/BunTestModule.h +++ b/src/bun.js/modules/BunTestModule.h @@ -6,7 +6,7 @@ void generateNativeModule_BunTest( Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto globalObject = jsCast(lexicalGlobalObject); JSObject* object = globalObject->lazyPreloadTestModuleObject(); diff --git a/src/bun.js/modules/NodeBufferModule.h b/src/bun.js/modules/NodeBufferModule.h index e53e29950ce196..2f791ab677386f 100644 --- a/src/bun.js/modules/NodeBufferModule.h +++ b/src/bun.js/modules/NodeBufferModule.h @@ -146,7 +146,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsGetter_INSPECT_MAX_BYTES, (JSGlobalObject * lexicalGl JSC_DEFINE_CUSTOM_SETTER(jsSetter_INSPECT_MAX_BYTES, (JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, PropertyName propertyName)) { auto globalObject = reinterpret_cast(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); auto val = JSValue::decode(value); Bun::V::validateNumber(scope, globalObject, val, jsString(vm, String("INSPECT_MAX_BYTES"_s)), jsNumber(0), jsUndefined()); diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp index b3973e7eaf794b..305b16ed1f7da5 100644 --- a/src/bun.js/modules/NodeModuleModule.cpp +++ b/src/bun.js/modules/NodeModuleModule.cpp @@ -147,7 +147,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleModuleConstructor, // In node, this is supposed to be the actual CommonJSModule constructor. // We are cutting a huge corner by not doing all that work. // This code is only to support babel. - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); JSString* idString = JSC::jsString(vm, WTF::String("."_s)); JSString* dirname = jsEmptyString(vm); @@ -192,7 +192,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsBuiltinModule, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue moduleName = callFrame->argument(0); if (!moduleName.isString()) { @@ -207,7 +207,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsBuiltinModule, JSC_DEFINE_HOST_FUNCTION(jsFunctionWrap, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSString* code = callFrame->argument(0).toStringOrNull(globalObject); RETURN_IF_EXCEPTION(scope, {}); @@ -229,7 +229,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionNodeModuleCreateRequire, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (callFrame->argumentCount() < 1) { return Bun::throwError(globalObject, scope, @@ -296,7 +296,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionSyncBuiltinExports, JSC_DEFINE_HOST_FUNCTION(jsFunctionSourceMap, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); throwException(globalObject, scope, createError(globalObject, "Not implemented"_s)); @@ -307,7 +307,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveFileName, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); switch (callFrame->argumentCount()) { case 0: { @@ -442,7 +442,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionResolveLookupPaths, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); String request = callFrame->argument(0).toWTFString(globalObject); @@ -501,7 +501,7 @@ extern "C" JSC::EncodedJSValue NodeModuleModule__findPath(JSGlobalObject*, JSC_DEFINE_HOST_FUNCTION(jsFunctionFindPath, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); JSValue request_value = callFrame->argument(0); @@ -820,7 +820,7 @@ void generateNativeModule_NodeModule(JSC::JSGlobalObject* lexicalGlobalObject, JSC::MarkedArgumentBuffer& exportValues) { Zig::GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto catchScope = DECLARE_CATCH_SCOPE(vm); auto* constructor = globalObject->m_nodeModuleConstructor.getInitializedOnMainThread( globalObject); diff --git a/src/bun.js/modules/NodeProcessModule.h b/src/bun.js/modules/NodeProcessModule.h index edde3fa5e5b592..5989dd9a8c0dcf 100644 --- a/src/bun.js/modules/NodeProcessModule.h +++ b/src/bun.js/modules/NodeProcessModule.h @@ -40,7 +40,7 @@ JSC_DEFINE_CUSTOM_SETTER(jsFunctionProcessModuleCommonJSSetter, DEFINE_NATIVE_MODULE(NodeProcess) { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); JSC::JSObject* process = globalObject->processObject(); diff --git a/src/bun.js/modules/NodeUtilTypesModule.cpp b/src/bun.js/modules/NodeUtilTypesModule.cpp index a34b87b7077945..69c8e40acc2476 100644 --- a/src/bun.js/modules/NodeUtilTypesModule.cpp +++ b/src/bun.js/modules/NodeUtilTypesModule.cpp @@ -15,6 +15,7 @@ #include #include #include +#include "ZigGeneratedClasses.h" #include "NodeUtilTypesModule.h" @@ -151,7 +152,15 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsNativeError, { GET_FIRST_VALUE if (value.isCell()) { - if (value.asCell()->type() == ErrorInstanceType) + JSCell* cell = value.asCell(); + if (cell->type() == ErrorInstanceType) + return JSValue::encode(jsBoolean(true)); + + // Workaround for https://github.com/oven-sh/bun/issues/11780 + // They have code that does + // assert(util.types.isNativeError(resolveMessage)) + // FIXME: delete this once ResolveMessage and BuildMessage extend Error + if (cell->inherits() || cell->inherits()) return JSValue::encode(jsBoolean(true)); } @@ -183,7 +192,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsAsyncFunction, return JSValue::encode(jsBoolean(true)); } - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto proto = function->getPrototype(vm, globalObject); if (!proto.isCell()) { return JSValue::encode(jsBoolean(false)); @@ -443,7 +452,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionIsKeyObject, auto* object = cell->getObject(); - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); const auto& names = WebCore::builtinNames(vm); auto scope = DECLARE_CATCH_SCOPE(vm); diff --git a/src/bun.js/modules/ObjectModule.cpp b/src/bun.js/modules/ObjectModule.cpp index 6854c31de70755..f4c363d43e0acd 100644 --- a/src/bun.js/modules/ObjectModule.cpp +++ b/src/bun.js/modules/ObjectModule.cpp @@ -10,14 +10,15 @@ generateObjectModuleSourceCode(JSC::JSGlobalObject* globalObject, JSC::Identifier moduleKey, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) -> void { - JSC::VM& vm = lexicalGlobalObject->vm(); - GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); JSC::EnsureStillAliveScope stillAlive(object); PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); - object->getPropertyNames(globalObject, properties, - DontEnumPropertiesMode::Exclude); + object->methodTable()->getOwnPropertyNames(object, globalObject, properties, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(throwScope, void()); gcUnprotectNullTolerant(object); for (auto& entry : properties) { @@ -43,7 +44,7 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, JSC::Identifier moduleKey, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) -> void { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); JSC::EnsureStillAliveScope stillAlive(object); @@ -97,7 +98,7 @@ generateJSValueExportDefaultObjectSourceCode(JSC::JSGlobalObject* globalObject, JSC::Identifier moduleKey, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) -> void { - JSC::VM& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(value); const Identifier& esModuleMarker = vm.propertyNames->__esModule; diff --git a/src/bun.js/modules/UTF8ValidateModule.h b/src/bun.js/modules/UTF8ValidateModule.h index a0ea1ff72d941c..e5d12b93a25032 100644 --- a/src/bun.js/modules/UTF8ValidateModule.h +++ b/src/bun.js/modules/UTF8ValidateModule.h @@ -9,7 +9,7 @@ generateNativeModule_UTF8Validate(JSC::JSGlobalObject* globalObject, Vector& exportNames, JSC::MarkedArgumentBuffer& exportValues) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(JSC::JSFunction::create( diff --git a/src/bun.js/modules/_NativeModule.h b/src/bun.js/modules/_NativeModule.h index 506dd05090e358..7b9e89cb3e87e6 100644 --- a/src/bun.js/modules/_NativeModule.h +++ b/src/bun.js/modules/_NativeModule.h @@ -25,7 +25,6 @@ // given is the default export #define BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE(macro) \ - macro("bun"_s, BunObject) \ macro("bun:test"_s, BunTest) \ macro("bun:jsc"_s, BunJSC) \ macro("node:buffer"_s, NodeBuffer) \ @@ -38,7 +37,8 @@ #define BUN_FOREACH_ESM_NATIVE_MODULE(macro) \ BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE(macro) \ macro("node:module"_s, NodeModule) \ - macro("node:process"_s, NodeProcess) + macro("node:process"_s, NodeProcess) \ + macro("bun"_s, BunObject) #define BUN_FOREACH_CJS_NATIVE_MODULE(macro) \ BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE(macro) diff --git a/src/bun.js/node/assert/myers_diff.zig b/src/bun.js/node/assert/myers_diff.zig index d6eb316c217182..4b51c63dd65c32 100644 --- a/src/bun.js/node/assert/myers_diff.zig +++ b/src/bun.js/node/assert/myers_diff.zig @@ -255,7 +255,7 @@ pub fn DifferWithEql(comptime Line: type, comptime opts: Options, comptime areLi try result.ensureUnusedCapacity(u(@max(x - prev_x, y - prev_y))); while (x > prev_x and y > prev_y) { const line: Line = blk: { - if (@typeInfo(Line) == .Pointer and comptime opts.check_comma_disparity) { + if (@typeInfo(Line) == .pointer and comptime opts.check_comma_disparity) { const actual_el = actual[u(x) - 1]; // actual[x-1].endsWith(',') break :blk if (actual_el[actual_el.len - 1] == ',') @@ -347,7 +347,7 @@ fn areStrLinesEqual(comptime T: type, a: T, b: T, comptime check_comma_disparity // []const u8 -> u8 const info = @typeInfo(T); - const ChildType = info.Pointer.child; + const ChildType = info.pointer.child; if (comptime !check_comma_disparity) { return mem.eql(ChildType, a, b); @@ -498,7 +498,7 @@ test StrDiffer { \\ 4, \\ 5, \\ 6, - \\ 7 + \\ 7 \\] , // expected @@ -509,7 +509,7 @@ test StrDiffer { \\ 4, \\ 5, \\ 9, - \\ 7 + \\ 7 \\] }, // // remove line diff --git a/src/bun.js/node/buffer.zig b/src/bun.js/node/buffer.zig index 86d4fc73c1e907..0bccfa0b9d02b8 100644 --- a/src/bun.js/node/buffer.zig +++ b/src/bun.js/node/buffer.zig @@ -82,7 +82,5 @@ pub const BufferVectorized = struct { }; comptime { - if (!JSC.is_bindgen) { - @export(BufferVectorized.fill, .{ .name = "Bun__Buffer_fill" }); - } + @export(&BufferVectorized.fill, .{ .name = "Bun__Buffer_fill" }); } diff --git a/src/bun.js/node/fs_events.zig b/src/bun.js/node/fs_events.zig index 9953527a6ebfb6..483da52d0ad732 100644 --- a/src/bun.js/node/fs_events.zig +++ b/src/bun.js/node/fs_events.zig @@ -79,13 +79,6 @@ pub const kFSEventStreamEventFlagRootChanged: c_int = 32; pub const kFSEventStreamEventFlagUnmount: c_int = 128; pub const kFSEventStreamEventFlagUserDropped: c_int = 2; -// Lazy function call binding. -const RTLD_LAZY = 0x1; -// Symbols exported from this image (dynamic library or bundle) -// are generally hidden and only availble to dlsym() when -// directly using the handle returned by this call to dlopen(). -const RTLD_LOCAL = 0x4; - pub const kFSEventsModified: c_int = kFSEventStreamEventFlagItemChangeOwner | kFSEventStreamEventFlagItemFinderInfoMod | @@ -191,7 +184,7 @@ var fsevents_cf: ?CoreFoundation = null; var fsevents_cs: ?CoreServices = null; fn InitLibrary() void { - const fsevents_cf_handle = bun.C.dlopen("/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", RTLD_LAZY | RTLD_LOCAL); + const fsevents_cf_handle = bun.C.dlopen("/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", .{ .LAZY = true, .LOCAL = true }); if (fsevents_cf_handle == null) @panic("Cannot Load CoreFoundation"); fsevents_cf = CoreFoundation{ @@ -210,7 +203,7 @@ fn InitLibrary() void { .RunLoopDefaultMode = dlsym(fsevents_cf_handle, *CFStringRef, "kCFRunLoopDefaultMode") orelse @panic("Cannot Load CoreFoundation"), }; - const fsevents_cs_handle = bun.C.dlopen("/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices", RTLD_LAZY | RTLD_LOCAL); + const fsevents_cs_handle = bun.C.dlopen("/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices", .{ .LAZY = true, .LOCAL = true }); if (fsevents_cs_handle == null) @panic("Cannot Load CoreServices"); fsevents_cs = CoreServices{ diff --git a/src/bun.js/node/node.classes.ts b/src/bun.js/node/node.classes.ts index ec1e7b4b42cd1d..bee94131c8fcb5 100644 --- a/src/bun.js/node/node.classes.ts +++ b/src/bun.js/node/node.classes.ts @@ -161,276 +161,6 @@ export default [ }, values: ["arguments", "callback"], }), - define({ - name: "Stats", - construct: true, - finalize: true, - klass: {}, - JSType: "0b11101110", - - // TODO: generate-classes needs to handle Object.create properly when - // functions are used. The functions need a fallback implementation to use - // getters. - supportsObjectCreate: true, - - proto: { - isBlockDevice: { - fn: "isBlockDevice_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isCharacterDevice: { - fn: "isCharacterDevice_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isDirectory: { - fn: "isDirectory_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isFIFO: { - fn: "isFIFO_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isFile: { - fn: "isFile_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isSocket: { - fn: "isSocket_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isSymbolicLink: { - fn: "isSymbolicLink_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - }, - own: { - dev: "dev", - ino: "ino", - mode: "mode", - nlink: "nlink", - uid: "uid", - gid: "gid", - rdev: "rdev", - size: "size", - blksize: "blksize", - blocks: "blocks", - atimeMs: "atimeMs", - mtimeMs: "mtimeMs", - ctimeMs: "ctimeMs", - birthtimeMs: "birthtimeMs", - atime: "atime", - mtime: "mtime", - ctime: "ctime", - birthtime: "birthtime", - }, - }), - define({ - name: "BigIntStats", - construct: true, - finalize: true, - klass: {}, - JSType: "0b11101110", - - // TODO: generate-classes needs to handle Object.create properly when - // functions are used. The functions need a fallback implementation to use - // getters. - supportsObjectCreate: true, - - proto: { - isBlockDevice: { - fn: "isBlockDevice_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isCharacterDevice: { - fn: "isCharacterDevice_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isDirectory: { - fn: "isDirectory_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isFIFO: { - fn: "isFIFO_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isFile: { - fn: "isFile_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isSocket: { - fn: "isSocket_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - isSymbolicLink: { - fn: "isSymbolicLink_", - length: 0, - enumerable: false, - DOMJIT: { - returns: "bool", - args: [], - pure: true, - }, - }, - }, - own: { - atime: "atime", - atimeMs: "atimeMs", - atimeNs: "atimeNs", - birthtime: "birthtime", - birthtimeMs: "birthtimeMs", - birthtimeNs: "birthtimeNs", - blksize: "blksize", - blocks: "blocks", - ctime: "ctime", - ctimeMs: "ctimeMs", - ctimeNs: "ctimeNs", - dev: "dev", - gid: "gid", - ino: "ino", - mode: "mode", - mtime: "mtime", - mtimeMs: "mtimeMs", - mtimeNs: "mtimeNs", - nlink: "nlink", - rdev: "rdev", - size: "size", - uid: "uid", - }, - }), - define({ - name: "Dirent", - construct: true, - finalize: true, - - klass: {}, - - // TODO: generate-classes needs to handle Object.create properly when - // functions are used. The functions need a fallback implementation to use - // getters. - supportsObjectCreate: true, - - proto: { - isBlockDevice: { - fn: "isBlockDevice", - length: 0, - }, - isCharacterDevice: { - fn: "isCharacterDevice", - length: 0, - }, - isDirectory: { - fn: "isDirectory", - length: 0, - }, - isFIFO: { - fn: "isFIFO", - length: 0, - }, - isFile: { - fn: "isFile", - length: 0, - }, - isSocket: { - fn: "isSocket", - length: 0, - }, - isSymbolicLink: { - fn: "isSymbolicLink", - length: 0, - }, - name: { - getter: "getName", - cache: true, - }, - path: { - getter: "getPath", - cache: true, - }, - parentPath: { - // @since node v20.12.x - getter: "getPath", - cache: true, - }, - }, - }), define({ name: "NodeJSFS", construct: true, diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 50f5f705a398e1..d2dd5eb6232bd6 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -43,10 +43,6 @@ const StringOrBuffer = JSC.Node.StringOrBuffer; const NodeFSFunctionEnum = std.meta.DeclEnum(JSC.Node.NodeFS); const UvFsCallback = fn (*uv.fs_t) callconv(.C) void; -const Stats = JSC.Node.Stats; -const Dirent = JSC.Node.Dirent; -const StatFS = JSC.Node.StatFS; - pub const default_permission = if (Environment.isPosix) Syscall.S.IRUSR | Syscall.S.IWUSR | @@ -1015,7 +1011,7 @@ pub const AsyncReaddirRecursiveTask = struct { pub const ResultListEntry = struct { pub const Value = union(Return.Readdir.Tag) { - with_file_types: std.ArrayList(Dirent), + with_file_types: std.ArrayList(bun.JSC.Node.Dirent), buffers: std.ArrayList(Buffer), files: std.ArrayList(bun.String), @@ -1096,7 +1092,7 @@ pub const AsyncReaddirRecursiveTask = struct { .root_path = PathString.init(bun.default_allocator.dupeZ(u8, args.path.slice()) catch bun.outOfMemory()), .result_list = switch (args.tag()) { .files => .{ .files = std.ArrayList(bun.String).init(bun.default_allocator) }, - .with_file_types => .{ .with_file_types = std.ArrayList(Dirent).init(bun.default_allocator) }, + .with_file_types => .{ .with_file_types = .init(bun.default_allocator) }, .buffers => .{ .buffers = std.ArrayList(Buffer).init(bun.default_allocator) }, }, }); @@ -1114,7 +1110,7 @@ pub const AsyncReaddirRecursiveTask = struct { inline else => |tag| { const ResultType = comptime switch (tag) { .files => bun.String, - .with_file_types => Dirent, + .with_file_types => bun.JSC.Node.Dirent, .buffers => Buffer, }; var stack = std.heap.stackFallback(8192, bun.default_allocator); @@ -1137,7 +1133,7 @@ pub const AsyncReaddirRecursiveTask = struct { for (entries.items) |*item| { switch (ResultType) { bun.String => item.deref(), - Dirent => item.deref(), + bun.JSC.Node.Dirent => item.deref(), Buffer => bun.default_allocator.free(item.buffer.byteSlice()), else => @compileError("unreachable"), } @@ -1174,7 +1170,7 @@ pub const AsyncReaddirRecursiveTask = struct { if (result.items.len > 0) { const Field = switch (ResultType) { bun.String => .files, - Dirent => .with_file_types, + bun.JSC.Node.Dirent => .with_file_types, Buffer => .buffers, else => @compileError("unreachable"), }; @@ -1604,7 +1600,7 @@ pub const Arguments = struct { }; fn wrapTo(T: type, in: i64) T { - comptime bun.assert(@typeInfo(T).Int.signedness == .unsigned); + comptime bun.assert(@typeInfo(T).int.signedness == .unsigned); return @intCast(@mod(in, std.math.maxInt(T))); } @@ -2207,7 +2203,7 @@ pub const Arguments = struct { } pub fn deinitAndUnprotect(this: *MkdirTemp) void { - this.prefix.deinit(); + this.prefix.deinitAndUnprotect(); } pub fn toThreadSafe(this: *MkdirTemp) void { @@ -2707,12 +2703,17 @@ pub const Arguments = struct { pub fn deinit(self: ReadFile) void { self.path.deinit(); if (self.signal) |signal| { + signal.pendingActivityUnref(); signal.unref(); } } pub fn deinitAndUnprotect(self: ReadFile) void { self.path.deinitAndUnprotect(); + if (self.signal) |signal| { + signal.pendingActivityUnref(); + signal.unref(); + } } pub fn toThreadSafe(self: *ReadFile) void { @@ -2729,7 +2730,10 @@ pub const Arguments = struct { var flag = FileSystemFlags.r; var abort_signal: ?*AbortSignal = null; - errdefer if (abort_signal) |signal| signal.unref(); + errdefer if (abort_signal) |signal| { + signal.pendingActivityUnref(); + signal.unref(); + }; if (arguments.next()) |arg| { arguments.eat(); @@ -2747,6 +2751,7 @@ pub const Arguments = struct { if (try arg.getTruthy(ctx, "signal")) |value| { if (AbortSignal.fromJS(value)) |signal| { abort_signal = signal.ref(); + signal.pendingActivityRef(); } else { return ctx.throwInvalidArgumentTypeValue("signal", "AbortSignal", value); } @@ -2790,6 +2795,7 @@ pub const Arguments = struct { self.file.deinit(); self.data.deinit(); if (self.signal) |signal| { + signal.pendingActivityUnref(); signal.unref(); } } @@ -2802,6 +2808,10 @@ pub const Arguments = struct { pub fn deinitAndUnprotect(self: *WriteFile) void { self.file.deinitAndUnprotect(); self.data.deinitAndUnprotect(); + if (self.signal) |signal| { + signal.pendingActivityUnref(); + signal.unref(); + } } pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!WriteFile { const path = try PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator) orelse { @@ -2817,6 +2827,12 @@ pub const Arguments = struct { var flag = FileSystemFlags.w; var mode: Mode = default_permission; var abort_signal: ?*AbortSignal = null; + + errdefer if (abort_signal) |signal| { + signal.pendingActivityUnref(); + signal.unref(); + }; + var flush: bool = false; if (data_value.isString()) { encoding = Encoding.utf8; @@ -2842,6 +2858,7 @@ pub const Arguments = struct { if (try arg.getTruthy(ctx, "signal")) |value| { if (AbortSignal.fromJS(value)) |signal| { abort_signal = signal.ref(); + signal.pendingActivityRef(); } else { return ctx.throwInvalidArgumentTypeValue("signal", "AbortSignal", value); } @@ -3019,7 +3036,7 @@ pub const Arguments = struct { dest: PathLike, mode: Constants.Copyfile, - pub fn deinit(this: CopyFile) void { + pub fn deinit(this: *const CopyFile) void { this.src.deinit(); this.dest.deinit(); } @@ -3029,7 +3046,7 @@ pub const Arguments = struct { this.dest.toThreadSafe(); } - pub fn deinitAndUnprotect(this: *CopyFile) void { + pub fn deinitAndUnprotect(this: *const CopyFile) void { this.src.deinitAndUnprotect(); this.dest.deinitAndUnprotect(); } @@ -3045,16 +3062,16 @@ pub const Arguments = struct { }; errdefer dest.deinit(); - var mode: Mode = 0; + var mode: Constants.Copyfile = @enumFromInt(0); if (arguments.next()) |arg| { arguments.eat(); - mode = @intFromEnum(try FileSystemFlags.fromJSNumberOnly(ctx, arg, .copy_file)); + mode = @enumFromInt(@intFromEnum(try FileSystemFlags.fromJSNumberOnly(ctx, arg, .copy_file))); } return CopyFile{ .src = src, .dest = dest, - .mode = @enumFromInt(mode), + .mode = mode, }; } }; @@ -3072,7 +3089,7 @@ pub const Arguments = struct { deinit_paths: bool = true, }; - fn deinit(this: *Cp) void { + pub fn deinit(this: *const Cp) void { if (this.flags.deinit_paths) { this.src.deinit(); this.dest.deinit(); @@ -3166,7 +3183,7 @@ pub const Arguments = struct { }; pub const StatOrNotFound = union(enum) { - stats: Stats, + stats: bun.JSC.Node.Stats, not_found: void, pub fn toJS(this: *StatOrNotFound, globalObject: *JSC.JSGlobalObject) JSC.JSValue { @@ -3214,7 +3231,7 @@ const Return = struct { pub const Chmod = void; pub const Fchown = void; pub const Fdatasync = void; - pub const Fstat = Stats; + pub const Fstat = bun.JSC.Node.Stats; pub const Rm = void; pub const Fsync = void; pub const Ftruncate = void; @@ -3228,7 +3245,7 @@ const Return = struct { pub const Open = FDImpl; pub const WriteFile = void; pub const Readv = Read; - pub const StatFS = JSC.Node.StatFS; + pub const StatFS = bun.JSC.Node.StatFS; pub const Read = struct { bytes_read: u52, @@ -3294,7 +3311,7 @@ const Return = struct { } }; pub const Readdir = union(Tag) { - with_file_types: []Dirent, + with_file_types: []bun.JSC.Node.Dirent, buffers: []Buffer, files: []const bun.String, @@ -3308,7 +3325,18 @@ const Return = struct { switch (this) { .with_file_types => { defer bun.default_allocator.free(this.with_file_types); - return JSC.toJS(globalObject, []Dirent, this.with_file_types, .temporary); + var array = JSC.JSValue.createEmptyArray(globalObject, this.with_file_types.len); + var previous_jsstring: ?*JSC.JSString = null; + for (this.with_file_types, 0..) |*item, i| { + const res = item.toJSNewlyCreated(globalObject, &previous_jsstring); + if (res == .zero) return .zero; + array.putIndex( + globalObject, + @truncate(i), + res, + ); + } + return array; }, .buffers => { defer bun.default_allocator.free(this.buffers); @@ -3325,7 +3353,7 @@ const Return = struct { pub const ReadFileWithOptions = union(enum) { string: string, transcoded_string: bun.String, - buffer: JSC.Node.Buffer, + buffer: Buffer, null_terminated: [:0]const u8, }; pub const Readlink = StringOrBuffer; @@ -3607,7 +3635,7 @@ pub const NodeFS = struct { // we fallback to copyfile() when the file is > 128 KB and clonefile fails // clonefile() isn't supported on all devices // nor is it supported across devices - var mode: Mode = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA; + var mode: u32 = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA; if (args.mode.shouldntOverwrite()) { mode |= C.darwin.COPYFILE_EXCL; } @@ -3638,7 +3666,7 @@ pub const NodeFS = struct { return Maybe(Return.CopyFile){ .err = .{ .errno = @intFromEnum(C.SystemErrno.ENOTSUP), .syscall = .copyfile } }; } - var flags: Mode = bun.O.CREAT | bun.O.WRONLY; + var flags: i32 = bun.O.CREAT | bun.O.WRONLY; var wrote: usize = 0; if (args.mode.shouldntOverwrite()) { flags |= bun.O.EXCL; @@ -3814,7 +3842,7 @@ pub const NodeFS = struct { pub fn fstat(_: *NodeFS, args: Arguments.Fstat, _: Flavor) Maybe(Return.Fstat) { return switch (Syscall.fstat(args.fd)) { - .result => |result| .{ .result = Stats.init(result, args.big_int) }, + .result => |result| .{ .result = .init(result, args.big_int) }, .err => |err| .{ .err = err }, }; } @@ -3885,13 +3913,13 @@ pub const NodeFS = struct { }; } - return Maybe(Return.Link).errnoSysPD(system.link(from, to, 0), .link, args.old_path.slice(), args.new_path.slice()) orelse + return Maybe(Return.Link).errnoSysPD(system.link(from, to), .link, args.old_path.slice(), args.new_path.slice()) orelse Maybe(Return.Link).success; } pub fn lstat(this: *NodeFS, args: Arguments.Lstat, _: Flavor) Maybe(Return.Lstat) { return switch (Syscall.lstat(args.path.sliceZ(&this.sync_error_buf))) { - .result => |result| Maybe(Return.Lstat){ .result = .{ .stats = Stats.init(result, args.big_int) } }, + .result => |result| Maybe(Return.Lstat){ .result = .{ .stats = .init(result, args.big_int) } }, .err => |err| brk: { if (!args.throw_if_no_entry and err.getErrno() == .NOENT) { return Maybe(Return.Lstat){ .result = .{ .not_found = {} } }; @@ -3962,7 +3990,7 @@ pub const NodeFS = struct { }; const Char = bun.OSPathChar; - const len = @as(u16, @truncate(path.len)); + const len: u16 = @truncate(path.len); // First, attempt to create the desired directory // If that fails, then walk back up the path until we have a match @@ -4411,7 +4439,7 @@ pub const NodeFS = struct { const maybe = switch (args.recursive) { inline else => |recursive| switch (args.tag()) { .buffers => readdirInner(&this.sync_error_buf, args, Buffer, recursive, flavor), - .with_file_types => readdirInner(&this.sync_error_buf, args, Dirent, recursive, flavor), + .with_file_types => readdirInner(&this.sync_error_buf, args, bun.JSC.Node.Dirent, recursive, flavor), .files => readdirInner(&this.sync_error_buf, args, bun.String, recursive, flavor), }, }; @@ -4433,7 +4461,7 @@ pub const NodeFS = struct { entries: *std.ArrayList(ExpectedType), ) Maybe(void) { const dir = fd.asDir(); - const is_u16 = comptime Environment.isWindows and (ExpectedType == bun.String or ExpectedType == Dirent); + const is_u16 = comptime Environment.isWindows and (ExpectedType == bun.String or ExpectedType == bun.JSC.Node.Dirent); var dirent_path: bun.String = bun.String.dead; defer { @@ -4454,7 +4482,7 @@ pub const NodeFS = struct { .err => |err| { for (entries.items) |*item| { switch (ExpectedType) { - Dirent => { + bun.JSC.Node.Dirent => { item.deref(); }, Buffer => { @@ -4475,7 +4503,7 @@ pub const NodeFS = struct { }, .result => |ent| ent, }) |current| : (entry = iterator.next()) { - if (ExpectedType == Dirent) { + if (ExpectedType == JSC.Node.Dirent) { if (dirent_path.isEmpty()) { dirent_path = JSC.WebCore.Encoder.toBunString(strings.withoutNTPrefix(std.meta.Child(@TypeOf(basename)), basename), args.encoding); } @@ -4483,7 +4511,7 @@ pub const NodeFS = struct { if (comptime !is_u16) { const utf8_name = current.name.slice(); switch (ExpectedType) { - Dirent => { + JSC.Node.Dirent => { dirent_path.ref(); entries.append(.{ .name = JSC.WebCore.Encoder.toBunString(utf8_name, args.encoding), @@ -4502,7 +4530,7 @@ pub const NodeFS = struct { } else { const utf16_name = current.name.slice(); switch (ExpectedType) { - Dirent => { + JSC.Node.Dirent => { dirent_path.ref(); entries.append(.{ .name = bun.String.createUTF16(utf16_name), @@ -4637,7 +4665,7 @@ pub const NodeFS = struct { } switch (comptime ExpectedType) { - Dirent => { + bun.JSC.Node.Dirent => { const path_u8 = bun.path.dirname(bun.path.join(&[_]string{ root_basename, name_to_copy }, .auto), .auto); if (dirent_path_prev.isEmpty() or !bun.strings.eql(dirent_path_prev.byteSlice(), path_u8)) { dirent_path_prev.deref(); @@ -4777,7 +4805,7 @@ pub const NodeFS = struct { } switch (comptime ExpectedType) { - Dirent => { + bun.JSC.Node.Dirent => { const path_u8 = bun.path.dirname(bun.path.join(&[_]string{ root_basename, name_to_copy }, .auto), .auto); if (dirent_path_prev.isEmpty() or !bun.strings.eql(dirent_path_prev.byteSlice(), path_u8)) { dirent_path_prev.deref(); @@ -4835,7 +4863,7 @@ pub const NodeFS = struct { comptime flavor: Flavor, ) Maybe(Return.Readdir) { const file_type = switch (ExpectedType) { - Dirent => "with_file_types", + bun.JSC.Node.Dirent => "with_file_types", bun.String => "files", Buffer => "buffers", else => @compileError("unreachable"), @@ -4851,7 +4879,7 @@ pub const NodeFS = struct { .err => |err| { for (entries.items) |*result| { switch (ExpectedType) { - Dirent => { + bun.JSC.Node.Dirent => { result.name.deref(); }, Buffer => { @@ -5351,7 +5379,7 @@ pub const NodeFS = struct { // If this errors, we silently ignore it. // Not all files are seekable (and thus, not all files can be truncated). if (Environment.isWindows) { - _ = std.os.windows.kernel32.SetEndOfFile(fd.cast()); + _ = bun.windows.SetEndOfFile(fd.cast()); } else { _ = Syscall.ftruncate(fd, @intCast(@as(u63, @truncate(written)))); } @@ -5722,7 +5750,7 @@ pub const NodeFS = struct { const path = args.path.sliceZ(&this.sync_error_buf); return switch (Syscall.stat(path)) { .result => |result| .{ - .result = .{ .stats = Stats.init(result, args.big_int) }, + .result = .{ .stats = .init(result, args.big_int) }, }, .err => |err| brk: { if (!args.throw_if_no_entry and err.getErrno() == .NOENT) { @@ -5909,8 +5937,8 @@ pub const NodeFS = struct { Maybe(Return.Utimes).success; } - bun.assert(args.mtime.tv_nsec <= 1e9); - bun.assert(args.atime.tv_nsec <= 1e9); + bun.assert(args.mtime.nsec <= 1e9); + bun.assert(args.atime.nsec <= 1e9); return switch (Syscall.utimens( args.path.sliceZ(&this.sync_error_buf), @@ -5944,8 +5972,8 @@ pub const NodeFS = struct { Maybe(Return.Utimes).success; } - bun.assert(args.mtime.tv_nsec <= 1e9); - bun.assert(args.atime.tv_nsec <= 1e9); + bun.assert(args.mtime.nsec <= 1e9); + bun.assert(args.atime.nsec <= 1e9); return switch (Syscall.lutimes(args.path.sliceZ(&this.sync_error_buf), args.atime, args.mtime)) { .err => |err| .{ .err = err.withPath(args.path.slice()) }, @@ -6222,7 +6250,7 @@ pub const NodeFS = struct { if (!posix.S.ISREG(stat_.mode)) { if (posix.S.ISLNK(stat_.mode)) { - var mode_: Mode = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA | C.darwin.COPYFILE_NOFOLLOW_SRC; + var mode_: u32 = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA | C.darwin.COPYFILE_NOFOLLOW_SRC; if (mode.shouldntOverwrite()) { mode_ |= C.darwin.COPYFILE_EXCL; } @@ -6309,7 +6337,7 @@ pub const NodeFS = struct { // we fallback to copyfile() when the file is > 128 KB and clonefile fails // clonefile() isn't supported on all devices // nor is it supported across devices - var mode_: Mode = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA | C.darwin.COPYFILE_NOFOLLOW_SRC; + var mode_: u32 = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA | C.darwin.COPYFILE_NOFOLLOW_SRC; if (mode.shouldntOverwrite()) { mode_ |= C.darwin.COPYFILE_EXCL; } @@ -6356,7 +6384,7 @@ pub const NodeFS = struct { } }; } - var flags: Mode = bun.O.CREAT | bun.O.WRONLY; + var flags: i32 = bun.O.CREAT | bun.O.WRONLY; var wrote: usize = 0; if (mode.shouldntOverwrite()) { flags |= bun.O.EXCL; @@ -6554,8 +6582,7 @@ pub export fn Bun__mkdirp(globalThis: *JSC.JSGlobalObject, path: [*:0]const u8) } comptime { - if (!JSC.is_bindgen) - _ = Bun__mkdirp; + _ = Bun__mkdirp; } /// Copied from std.fs.Dir.deleteTree. This function returns `FileNotFound` instead of ignoring it, which @@ -6819,7 +6846,7 @@ fn zigDeleteTreeMinStackSizeWithKindHint(self: std.fs.Dir, sub_path: []const u8, // Valid use of MAX_PATH_BYTES because dir_name_buf will only // ever store a single path component that was returned from the // filesystem. - var dir_name_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var dir_name_buf: [std.fs.max_path_bytes]u8 = undefined; var dir_name: []const u8 = sub_path; // Here we must avoid recursion, in order to provide O(1) memory guarantee of this function. diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 0682d1f46559fb..feb633c2e0eacf 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -18,7 +18,7 @@ const NodeFSFunctionEnum = std.meta.DeclEnum(JSC.Node.NodeFS); /// Async calls use a thread pool. fn Bindings(comptime function_name: NodeFSFunctionEnum) type { const function = @field(JSC.Node.NodeFS, @tagName(function_name)); - const fn_info = @typeInfo(@TypeOf(function)).Fn; + const fn_info = @typeInfo(@TypeOf(function)).@"fn"; if (fn_info.params.len != 3) { @compileError("Expected fn(NodeFS, Arguments) Return for NodeFS." ++ @tagName(function_name)); } @@ -49,15 +49,20 @@ fn Bindings(comptime function_name: NodeFSFunctionEnum) type { pub fn runAsync(this: *JSC.Node.NodeJSFS, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var slice = ArgumentsSlice.init(globalObject.bunVM(), callframe.arguments()); slice.will_be_async = true; + var deinit = false; - const args = if (Arguments != void) + defer if (deinit) slice.deinit(); + + var args = if (Arguments != void) Arguments.fromJS(globalObject, &slice) catch |err| { - slice.deinit(); + deinit = true; return err; }; + defer if (deinit) args.deinit(); + if (globalObject.hasException()) { - slice.deinit(); + deinit = true; return .zero; } @@ -65,7 +70,7 @@ fn Bindings(comptime function_name: NodeFSFunctionEnum) type { if (have_abort_signal) check_early_abort: { const signal = args.signal orelse break :check_early_abort; if (signal.reasonIfAborted(globalObject)) |reason| { - slice.deinit(); + deinit = true; return JSC.JSPromise.rejectedPromiseValue(globalObject, reason.toJS(globalObject)); } } diff --git a/src/bun.js/node/node_fs_stat_watcher.zig b/src/bun.js/node/node_fs_stat_watcher.zig index aefac5ef91fcf4..5fac2538b4d81c 100644 --- a/src/bun.js/node/node_fs_stat_watcher.zig +++ b/src/bun.js/node/node_fs_stat_watcher.zig @@ -26,9 +26,9 @@ const log = bun.Output.scoped(.StatWatcher, false); fn statToJSStats(globalThis: *JSC.JSGlobalObject, stats: bun.Stat, bigint: bool) JSC.JSValue { if (bigint) { - return StatsBig.new(StatsBig.init(stats)).toJS(globalThis); + return StatsBig.init(stats).toJS(globalThis); } else { - return StatsSmall.new(StatsSmall.init(stats)).toJS(globalThis); + return StatsSmall.init(stats).toJS(globalThis); } } @@ -86,19 +86,17 @@ pub const StatWatcherScheduler = struct { /// Set the timer (this function is not thread safe, should be called only from the main thread) fn setTimer(this: *StatWatcherScheduler, interval: i32) void { - // if the timer is active we need to remove it - if (this.event_loop_timer.state == .ACTIVE) { - this.vm.timer.remove(&this.event_loop_timer); - } - // if the interval is 0 means that we stop the timer if (interval == 0) { + // if the timer is active we need to remove it + if (this.event_loop_timer.state == .ACTIVE) { + this.vm.timer.remove(&this.event_loop_timer); + } return; } // reschedule the timer - this.event_loop_timer.next = bun.timespec.msFromNow(interval); - this.vm.timer.insert(&this.event_loop_timer); + this.vm.timer.update(&this.event_loop_timer, &bun.timespec.msFromNow(interval)); } /// Schedule a task to set the timer in the main thread @@ -309,8 +307,6 @@ pub const StatWatcher = struct { } pub fn hasPendingActivity(this: *StatWatcher) bool { - @fence(.acquire); - return this.used_by_scheduler_thread.load(.acquire); } diff --git a/src/bun.js/node/node_fs_watcher.zig b/src/bun.js/node/node_fs_watcher.zig index bd511c0e92bf8c..55c2af8c892853 100644 --- a/src/bun.js/node/node_fs_watcher.zig +++ b/src/bun.js/node/node_fs_watcher.zig @@ -572,7 +572,6 @@ pub const FSWatcher = struct { // this can be called from Watcher Thread or JS Context Thread pub fn refTask(this: *FSWatcher) bool { - @fence(.acquire); this.mutex.lock(); defer this.mutex.unlock(); if (this.closed) return false; @@ -582,7 +581,6 @@ pub const FSWatcher = struct { } pub fn hasPendingActivity(this: *FSWatcher) bool { - @fence(.acquire); return this.pending_activity_count.load(.acquire) > 0; } diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig index fc60648fee1385..ee4eaf3aa9f637 100644 --- a/src/bun.js/node/node_os.zig +++ b/src/bun.js/node/node_os.zig @@ -88,7 +88,7 @@ fn cpusImplLinux(globalThis: *JSC.JSGlobalObject) !JSC.JSValue { // Read each CPU line while (line_iter.next()) |line| { // CPU lines are formatted as `cpu0 user nice sys idle iowait irq softirq` - var toks = std.mem.tokenize(u8, line, " \t"); + var toks = std.mem.tokenizeAny(u8, line, " \t"); const cpu_name = toks.next(); if (cpu_name == null or !std.mem.startsWith(u8, cpu_name.?, "cpu")) break; // done with CPUs diff --git a/src/bun.js/node/node_zlib_binding.zig b/src/bun.js/node/node_zlib_binding.zig index cd233554c775b3..ceb1a605f3ecb1 100644 --- a/src/bun.js/node/node_zlib_binding.zig +++ b/src/bun.js/node/node_zlib_binding.zig @@ -310,7 +310,7 @@ const CountedKeepAlive = struct { }; pub const SNativeZlib = struct { - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub usingnamespace JSC.Codegen.JSNativeZlib; pub usingnamespace CompressionStream(@This()); @@ -676,7 +676,7 @@ const ZlibContext = struct { pub const NativeBrotli = JSC.Codegen.JSNativeBrotli.getConstructor; pub const SNativeBrotli = struct { - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub usingnamespace JSC.Codegen.JSNativeBrotli; pub usingnamespace CompressionStream(@This()); diff --git a/src/bun.js/node/path.zig b/src/bun.js/node/path.zig index 3545f4418de694..cabfc69be5d1ca 100644 --- a/src/bun.js/node/path.zig +++ b/src/bun.js/node/path.zig @@ -970,25 +970,44 @@ pub fn format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]J const allocator = stack_fallback.get(); var root: []const u8 = ""; + var root_slice: ?JSC.ZigString.Slice = null; + defer if (root_slice) |slice| slice.deinit(); + if (try pathObject_ptr.getTruthy(globalObject, "root")) |jsValue| { - root = jsValue.toSlice(globalObject, allocator).slice(); + root_slice = try jsValue.toSlice(globalObject, allocator); + root = root_slice.?.slice(); } var dir: []const u8 = ""; + var dir_slice: ?JSC.ZigString.Slice = null; + defer if (dir_slice) |slice| slice.deinit(); + if (try pathObject_ptr.getTruthy(globalObject, "dir")) |jsValue| { - dir = jsValue.toSlice(globalObject, allocator).slice(); + dir_slice = try jsValue.toSlice(globalObject, allocator); + dir = dir_slice.?.slice(); } var base: []const u8 = ""; + var base_slice: ?JSC.ZigString.Slice = null; + defer if (base_slice) |slice| slice.deinit(); + if (try pathObject_ptr.getTruthy(globalObject, "base")) |jsValue| { - base = jsValue.toSlice(globalObject, allocator).slice(); + base_slice = try jsValue.toSlice(globalObject, allocator); + base = base_slice.?.slice(); } - // Prefix with _ to avoid shadowing the identifier in the outer scope. var _name: []const u8 = ""; + var _name_slice: ?JSC.ZigString.Slice = null; + defer if (_name_slice) |slice| slice.deinit(); + if (try pathObject_ptr.getTruthy(globalObject, "name")) |jsValue| { - _name = jsValue.toSlice(globalObject, allocator).slice(); + _name_slice = try jsValue.toSlice(globalObject, allocator); + _name = _name_slice.?.slice(); } var ext: []const u8 = ""; + var ext_slice: ?JSC.ZigString.Slice = null; + defer if (ext_slice) |slice| slice.deinit(); + if (try pathObject_ptr.getTruthy(globalObject, "ext")) |jsValue| { - ext = jsValue.toSlice(globalObject, allocator).slice(); + ext_slice = try jsValue.toSlice(globalObject, allocator); + ext = ext_slice.?.slice(); } return formatJS_T(u8, globalObject, allocator, isWindows, .{ .root = root, .dir = dir, .base = base, .ext = ext, .name = _name }); } @@ -2795,7 +2814,7 @@ pub fn resolveJS_T(comptime T: type, globalObject: *JSC.JSGlobalObject, allocato return if (isWindows) resolveWindowsJS_T(T, globalObject, paths, buf, buf2) else resolvePosixJS_T(T, globalObject, paths, buf, buf2); } -extern "C" fn Process__getCachedCwd(*JSC.JSGlobalObject) JSC.JSValue; +extern "c" fn Process__getCachedCwd(*JSC.JSGlobalObject) JSC.JSValue; pub fn resolve(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { var arena = bun.ArenaAllocator.init(bun.default_allocator); @@ -2957,17 +2976,17 @@ pub fn toNamespacedPath(globalObject: *JSC.JSGlobalObject, isWindows: bool, args pub const Extern = [_][]const u8{"create"}; comptime { - @export(Path.basename, .{ .name = "Bun__Path__basename" }); - @export(Path.dirname, .{ .name = "Bun__Path__dirname" }); - @export(Path.extname, .{ .name = "Bun__Path__extname" }); - @export(path_format, .{ .name = "Bun__Path__format" }); - @export(Path.isAbsolute, .{ .name = "Bun__Path__isAbsolute" }); - @export(Path.join, .{ .name = "Bun__Path__join" }); - @export(Path.normalize, .{ .name = "Bun__Path__normalize" }); - @export(Path.parse, .{ .name = "Bun__Path__parse" }); - @export(Path.relative, .{ .name = "Bun__Path__relative" }); - @export(Path.resolve, .{ .name = "Bun__Path__resolve" }); - @export(Path.toNamespacedPath, .{ .name = "Bun__Path__toNamespacedPath" }); + @export(&Path.basename, .{ .name = "Bun__Path__basename" }); + @export(&Path.dirname, .{ .name = "Bun__Path__dirname" }); + @export(&Path.extname, .{ .name = "Bun__Path__extname" }); + @export(&path_format, .{ .name = "Bun__Path__format" }); + @export(&Path.isAbsolute, .{ .name = "Bun__Path__isAbsolute" }); + @export(&Path.join, .{ .name = "Bun__Path__join" }); + @export(&Path.normalize, .{ .name = "Bun__Path__normalize" }); + @export(&Path.parse, .{ .name = "Bun__Path__parse" }); + @export(&Path.relative, .{ .name = "Bun__Path__relative" }); + @export(&Path.resolve, .{ .name = "Bun__Path__resolve" }); + @export(&Path.toNamespacedPath, .{ .name = "Bun__Path__toNamespacedPath" }); } fn path_format(globalObject: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(JSC.conv) JSC.JSValue { diff --git a/src/bun.js/node/path_watcher.zig b/src/bun.js/node/path_watcher.zig index 71cfd3c631e3d7..9e647386c3350b 100644 --- a/src/bun.js/node/path_watcher.zig +++ b/src/bun.js/node/path_watcher.zig @@ -51,7 +51,6 @@ pub const PathWatcherManager = struct { }; fn refPendingTask(this: *PathWatcherManager) bool { - @fence(.release); this.mutex.lock(); defer this.mutex.unlock(); if (this.deinit_on_last_task) return false; @@ -61,12 +60,10 @@ pub const PathWatcherManager = struct { } fn hasPendingTasks(this: *PathWatcherManager) callconv(.C) bool { - @fence(.acquire); return this.has_pending_tasks.load(.acquire); } fn unrefPendingTask(this: *PathWatcherManager) void { - @fence(.release); this.mutex.lock(); defer this.mutex.unlock(); this.pending_tasks -= 1; @@ -830,7 +827,6 @@ pub const PathWatcher = struct { } pub fn refPendingDirectory(this: *PathWatcher) bool { - @fence(.release); this.mutex.lock(); defer this.mutex.unlock(); if (this.isClosed()) return false; @@ -840,24 +836,20 @@ pub const PathWatcher = struct { } pub fn hasPendingDirectories(this: *PathWatcher) callconv(.C) bool { - @fence(.acquire); return this.has_pending_directories.load(.acquire); } pub fn isClosed(this: *PathWatcher) bool { - @fence(.acquire); return this.closed.load(.acquire); } pub fn setClosed(this: *PathWatcher) void { this.mutex.lock(); defer this.mutex.unlock(); - @fence(.release); this.closed.store(true, .release); } pub fn unrefPendingDirectory(this: *PathWatcher) void { - @fence(.release); this.mutex.lock(); defer this.mutex.unlock(); this.pending_directories -= 1; diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index eee96c0c5a11b8..a065cf635f1842 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -4,7 +4,6 @@ const bun = @import("root").bun; const meta = bun.meta; const windows = bun.windows; const heap_allocator = bun.default_allocator; -const is_bindgen: bool = false; const kernel32 = windows.kernel32; const logger = bun.logger; const posix = std.posix; @@ -200,9 +199,9 @@ pub fn Maybe(comptime ReturnTypeT: type, comptime ErrorTypeT: type) type { []u8 => JSC.ArrayBuffer.fromBytes(r, .ArrayBuffer).toJS(globalObject, null), else => switch (@typeInfo(ReturnType)) { - .Int, .Float, .ComptimeInt, .ComptimeFloat => JSC.JSValue.jsNumber(r), - .Struct, .Enum, .Opaque, .Union => r.toJS(globalObject), - .Pointer => { + .int, .float, .comptime_int, .comptime_float => JSC.JSValue.jsNumber(r), + .@"struct", .@"enum", .@"opaque", .@"union" => r.toJS(globalObject), + .pointer => { if (bun.trait.isZigString(ReturnType)) JSC.ZigString.init(bun.asByteSlice(r)).withEncoding().toJS(globalObject); @@ -932,15 +931,15 @@ pub const PathLike = union(enum) { return buf[0..sliced.len :0]; } - pub inline fn sliceZ(this: PathLike, buf: *bun.PathBuffer) [:0]const u8 { + pub fn sliceZ(this: PathLike, buf: *bun.PathBuffer) callconv(bun.callconv_inline) [:0]const u8 { return sliceZWithForceCopy(this, buf, false); } - pub inline fn sliceW(this: PathLike, buf: *bun.WPathBuffer) [:0]const u16 { + pub fn sliceW(this: PathLike, buf: *bun.WPathBuffer) callconv(bun.callconv_inline) [:0]const u16 { return strings.toWPath(buf, this.slice()); } - pub inline fn osPath(this: PathLike, buf: *bun.OSPathBuffer) bun.OSPathSliceZ { + pub fn osPath(this: PathLike, buf: *bun.OSPathBuffer) callconv(bun.callconv_inline) bun.OSPathSliceZ { if (comptime Environment.isWindows) { return sliceW(this, buf); } @@ -948,7 +947,7 @@ pub const PathLike = union(enum) { return sliceZWithForceCopy(this, buf, false); } - pub inline fn osPathKernel32(this: PathLike, buf: *bun.PathBuffer) bun.OSPathSliceZ { + pub fn osPathKernel32(this: PathLike, buf: *bun.PathBuffer) callconv(bun.callconv_inline) bun.OSPathSliceZ { if (comptime Environment.isWindows) { const s = this.slice(); const b = bun.PathBufferPool.get(); @@ -958,7 +957,7 @@ pub const PathLike = union(enum) { const normal = path_handler.normalizeBuf(resolve, b, .windows); return strings.toKernel32Path(@alignCast(std.mem.bytesAsSlice(u16, buf)), normal); } - const normal = path_handler.normalizeBuf(s, b, .windows); + const normal = path_handler.normalizeStringBuf(s, b, true, .windows, false); return strings.toKernel32Path(@alignCast(std.mem.bytesAsSlice(u16, buf)), normal); } @@ -1286,8 +1285,8 @@ fn timeLikeFromSeconds(seconds: f64) TimeLike { return seconds; } return .{ - .tv_sec = @intFromFloat(seconds), - .tv_nsec = @intFromFloat(@mod(seconds, 1) * std.time.ns_per_s), + .sec = @intFromFloat(seconds), + .nsec = @intFromFloat(@mod(seconds, 1) * std.time.ns_per_s), }; } @@ -1305,8 +1304,8 @@ fn timeLikeFromMilliseconds(milliseconds: f64) TimeLike { } return .{ - .tv_sec = @intFromFloat(sec), - .tv_nsec = @intFromFloat(nsec), + .sec = @intFromFloat(sec), + .nsec = @intFromFloat(nsec), }; } @@ -1336,15 +1335,15 @@ fn timeLikeFromNow() TimeLike { // ownership or permission checks are performed, and the file // timestamps are not modified, but other error conditions may still return .{ - .tv_sec = 0, - .tv_nsec = if (Environment.isLinux) std.os.linux.UTIME.NOW else bun.C.translated.UTIME_NOW, + .sec = 0, + .nsec = if (Environment.isLinux) std.os.linux.UTIME.NOW else bun.C.translated.UTIME_NOW, }; } pub fn modeFromJS(ctx: JSC.C.JSContextRef, value: JSC.JSValue) bun.JSError!?Mode { const mode_int = if (value.isNumber()) brk: { const m = try validators.validateUint32(ctx, value, "mode", .{}, false); - break :brk @as(Mode, @as(u24, @truncate(m))); + break :brk @as(Mode, @truncate(m)); } else brk: { if (value.isUndefinedOrNull()) return null; @@ -1439,8 +1438,8 @@ pub const PathOrFileDescriptor = union(Tag) { } }; -pub const FileSystemFlags = enum(if (Environment.isWindows) c_int else c_uint) { - pub const tag_type = @typeInfo(FileSystemFlags).Enum.tag_type; +pub const FileSystemFlags = enum(c_int) { + pub const tag_type = @typeInfo(FileSystemFlags).@"enum".tag_type; const O = bun.O; /// Open file for appending. The file is created if it does not exist. @@ -1474,7 +1473,7 @@ pub const FileSystemFlags = enum(if (Environment.isWindows) c_int else c_uint) { _, - const map = bun.ComptimeStringMap(Mode, .{ + const map = bun.ComptimeStringMap(i32, .{ .{ "r", O.RDONLY }, .{ "rs", O.RDONLY | O.SYNC }, .{ "sr", O.RDONLY | O.SYNC }, @@ -1550,7 +1549,7 @@ pub const FileSystemFlags = enum(if (Environment.isWindows) c_int else c_uint) { return ctx.throwInvalidArguments("Invalid flag '{any}'. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{str}); } - const flags = brk: { + const flags: i32 = brk: { switch (str.is16Bit()) { inline else => |is_16bit| { const chars = if (is_16bit) str.utf16SliceAligned() else str.slice(); @@ -1561,20 +1560,20 @@ pub const FileSystemFlags = enum(if (Environment.isWindows) c_int else c_uint) { const slice = str.toSlice(bun.default_allocator); defer slice.deinit(); - break :brk std.fmt.parseInt(Mode, slice.slice(), 10) catch null; + break :brk @as(i32, @intCast(std.fmt.parseInt(Mode, slice.slice(), 10) catch break :brk null)); } else { - break :brk std.fmt.parseInt(Mode, chars, 10) catch null; + break :brk @as(i32, @intCast(std.fmt.parseInt(Mode, chars, 10) catch break :brk null)); } } }, } - break :brk map.getWithEql(str, JSC.ZigString.eqlComptime); + break :brk map.getWithEql(str, JSC.ZigString.eqlComptime) orelse break :brk null; } orelse { return ctx.throwInvalidArguments("Invalid flag '{any}'. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{str}); }; - return @as(FileSystemFlags, @enumFromInt(@as(Mode, @intCast(flags)))); + return @enumFromInt(flags); } return null; @@ -1615,65 +1614,24 @@ pub const FileSystemFlags = enum(if (Environment.isWindows) c_int else c_uint) { /// Stats and BigIntStats classes from node:fs pub fn StatType(comptime big: bool) type { - const Int = if (big) i64 else i32; - const Float = if (big) i64 else f64; - const Timestamp = if (big) u64 else u0; - - const Date = packed struct { - value: Float, - pub inline fn toJS(this: @This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue { - const milliseconds = JSC.JSValue.jsNumber(this.value); - const array: [1]JSC.C.JSValueRef = .{milliseconds.asObjectRef()}; - return JSC.JSValue.c(JSC.C.JSObjectMakeDate(globalObject, 1, &array, null)); - } - }; - - return extern struct { - pub usingnamespace if (big) JSC.Codegen.JSBigIntStats else JSC.Codegen.JSStats; + return struct { pub usingnamespace bun.New(@This()); - - // Stats stores these as i32, but BigIntStats stores all of these as i64 - // On windows, these two need to be u64 as the numbers are often very large. - dev: u64, - ino: u64, - mode: Int, - nlink: Int, - uid: Int, - gid: Int, - rdev: Int, - blksize: Int, - blocks: Int, - - // Always store size as a 64-bit integer - size: i64, - - // _ms is either a float if Small, or a 64-bit integer if Big - atime_ms: Float, - mtime_ms: Float, - ctime_ms: Float, - birthtime_ms: Float, - - // _ns is a u64 storing nanosecond precision. it is a u0 when not BigIntStats - atime_ns: Timestamp = 0, - mtime_ns: Timestamp = 0, - ctime_ns: Timestamp = 0, - birthtime_ns: Timestamp = 0, - - const This = @This(); + value: bun.Stat, const StatTimespec = if (Environment.isWindows) bun.windows.libuv.uv_timespec_t else std.posix.timespec; + const Float = if (big) i64 else f64; - inline fn toNanoseconds(ts: StatTimespec) Timestamp { - if (ts.tv_sec < 0) { + inline fn toNanoseconds(ts: StatTimespec) u64 { + if (ts.sec < 0) { return @intCast(@max(bun.timespec.nsSigned(&bun.timespec{ - .sec = @intCast(ts.tv_sec), - .nsec = @intCast(ts.tv_nsec), + .sec = @intCast(ts.sec), + .nsec = @intCast(ts.nsec), }), 0)); } return bun.timespec.ns(&bun.timespec{ - .sec = @intCast(ts.tv_sec), - .nsec = @intCast(ts.tv_nsec), + .sec = @intCast(ts.sec), + .nsec = @intCast(ts.nsec), }); } @@ -1683,8 +1641,8 @@ pub fn StatType(comptime big: bool) type { // > libuv calculates tv_sec and tv_nsec from it and converts to signed long, // > which causes Y2038 overflow. On the other platforms it is safe to treat // > negative values as pre-epoch time. - const tv_sec = if (Environment.isWindows) @as(u32, @bitCast(ts.tv_sec)) else ts.tv_sec; - const tv_nsec = if (Environment.isWindows) @as(u32, @bitCast(ts.tv_nsec)) else ts.tv_nsec; + const tv_sec = if (Environment.isWindows) @as(u32, @bitCast(ts.sec)) else ts.sec; + const tv_nsec = if (Environment.isWindows) @as(u32, @bitCast(ts.nsec)) else ts.nsec; if (big) { const sec: i64 = tv_sec; const nsec: i64 = tv_nsec; @@ -1698,210 +1656,129 @@ pub fn StatType(comptime big: bool) type { } } - const PropertyGetter = fn (this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue; - - fn getter(comptime field: meta.FieldEnum(This)) PropertyGetter { - return struct { - pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - const value = @field(this, @tagName(field)); - const Type = @TypeOf(value); - if (comptime big and @typeInfo(Type) == .Int) { - if (Type == u64) { - return JSC.JSValue.fromUInt64NoTruncate(globalObject, value); - } - - return JSC.JSValue.fromInt64NoTruncate(globalObject, value); - } - - return JSC.JSValue.jsNumber(value); - } - }.callback; + pub fn toJS(this: *const @This(), globalObject: *JSC.JSGlobalObject) JSC.JSValue { + return statToJS(&this.value, globalObject); } - fn dateGetter(comptime field: meta.FieldEnum(This)) PropertyGetter { - return struct { - pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - const value = @field(this, @tagName(field)); - // Doing `Date{ ... }` here shouldn't actually change the memory layout of `value` - // but it will tell comptime code how to convert the i64/f64 to a JS Date. - return globalObject.toJS(Date{ .value = value }, .temporary); - } - }.callback; - } - - pub const isBlockDevice_ = JSC.wrapInstanceMethod(This, "isBlockDevice", false); - pub const isCharacterDevice_ = JSC.wrapInstanceMethod(This, "isCharacterDevice", false); - pub const isDirectory_ = JSC.wrapInstanceMethod(This, "isDirectory", false); - pub const isFIFO_ = JSC.wrapInstanceMethod(This, "isFIFO", false); - pub const isFile_ = JSC.wrapInstanceMethod(This, "isFile", false); - pub const isSocket_ = JSC.wrapInstanceMethod(This, "isSocket", false); - pub const isSymbolicLink_ = JSC.wrapInstanceMethod(This, "isSymbolicLink", false); - - pub const isBlockDevice_WithoutTypeChecks = domCall(.isBlockDevice); - pub const isCharacterDevice_WithoutTypeChecks = domCall(.isCharacterDevice); - pub const isDirectory_WithoutTypeChecks = domCall(.isDirectory); - pub const isFIFO_WithoutTypeChecks = domCall(.isFIFO); - pub const isFile_WithoutTypeChecks = domCall(.isFile); - pub const isSocket_WithoutTypeChecks = domCall(.isSocket); - pub const isSymbolicLink_WithoutTypeChecks = domCall(.isSymbolicLink); - - const DOMCallFn = fn ( - *This, - *JSC.JSGlobalObject, - ) bun.JSError!JSC.JSValue; - fn domCall(comptime decl: meta.DeclEnum(This)) DOMCallFn { - return struct { - pub fn run( - this: *This, - _: *JSC.JSGlobalObject, - ) bun.JSError!JSC.JSValue { - return @field(This, @tagName(decl))(this); - } - }.run; - } - - pub const dev = getter(.dev); - pub const ino = getter(.ino); - pub const mode = getter(.mode); - pub const nlink = getter(.nlink); - pub const uid = getter(.uid); - pub const gid = getter(.gid); - pub const rdev = getter(.rdev); - pub const size = getter(.size); - pub const blksize = getter(.blksize); - pub const blocks = getter(.blocks); - pub const atime = dateGetter(.atime_ms); - pub const mtime = dateGetter(.mtime_ms); - pub const ctime = dateGetter(.ctime_ms); - pub const birthtime = dateGetter(.birthtime_ms); - pub const atimeMs = getter(.atime_ms); - pub const mtimeMs = getter(.mtime_ms); - pub const ctimeMs = getter(.ctime_ms); - pub const birthtimeMs = getter(.birthtime_ms); - pub const atimeNs = getter(.atime_ns); - pub const mtimeNs = getter(.mtime_ns); - pub const ctimeNs = getter(.ctime_ns); - pub const birthtimeNs = getter(.birthtime_ns); - - inline fn modeInternal(this: *This) i32 { - return @truncate(this.mode); + pub fn getConstructor(globalObject: *JSC.JSGlobalObject) JSC.JSValue { + return if (big) Bun__JSBigIntStatsObjectConstructor(globalObject) else Bun__JSStatsObjectConstructor(globalObject); } - const S = if (Environment.isWindows) bun.C.S else posix.system.S; - - pub fn isBlockDevice(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(S.ISBLK(@intCast(this.modeInternal()))); - } - - pub fn isCharacterDevice(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(S.ISCHR(@intCast(this.modeInternal()))); - } - - pub fn isDirectory(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(S.ISDIR(@intCast(this.modeInternal()))); - } - - pub fn isFIFO(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(S.ISFIFO(@intCast(this.modeInternal()))); - } - - pub fn isFile(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(bun.isRegularFile(this.modeInternal())); - } - - pub fn isSocket(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(S.ISSOCK(@intCast(this.modeInternal()))); - } - - /// Node.js says this method is only valid on the result of lstat() - /// so it's fine if we just include it on stat() because it would - /// still just return false. - /// - /// See https://nodejs.org/api/fs.html#statsissymboliclink - pub fn isSymbolicLink(this: *This) JSC.JSValue { - return JSC.JSValue.jsBoolean(S.ISLNK(@intCast(this.modeInternal()))); - } - - // TODO: BigIntStats includes a `_checkModeProperty` but I dont think anyone actually uses it. - - pub fn finalize(this: *This) void { - this.destroy(); - } - - pub fn init(stat_: bun.Stat) This { + fn statToJS(stat_: *const bun.Stat, globalObject: *JSC.JSGlobalObject) JSC.JSValue { const aTime = stat_.atime(); const mTime = stat_.mtime(); const cTime = stat_.ctime(); + const dev: i64 = @intCast(@max(stat_.dev, 0)); + const ino: i64 = @intCast(@max(stat_.ino, 0)); + const mode: i64 = @truncate(@as(i64, @intCast(stat_.mode))); + const nlink: i64 = @truncate(@as(i64, @intCast(stat_.nlink))); + const uid: i64 = @truncate(@as(i64, @intCast(stat_.uid))); + const gid: i64 = @truncate(@as(i64, @intCast(stat_.gid))); + const rdev: i64 = @truncate(@as(i64, @intCast(stat_.rdev))); + const size: i64 = @truncate(@as(i64, @intCast(stat_.size))); + const blksize: i64 = @truncate(@as(i64, @intCast(stat_.blksize))); + const blocks: i64 = @truncate(@as(i64, @intCast(stat_.blocks))); + const atime_ms: Float = toTimeMS(aTime); + const mtime_ms: Float = toTimeMS(mTime); + const ctime_ms: Float = toTimeMS(cTime); + const atime_ns: u64 = if (big) toNanoseconds(aTime) else 0; + const mtime_ns: u64 = if (big) toNanoseconds(mTime) else 0; + const ctime_ns: u64 = if (big) toNanoseconds(cTime) else 0; + const birthtime_ms: Float = if (Environment.isLinux) 0 else toTimeMS(stat_.birthtime()); + const birthtime_ns: u64 = if (big and !Environment.isLinux) toNanoseconds(stat_.birthtime()) else 0; - return .{ - .dev = @intCast(@max(stat_.dev, 0)), - .ino = @intCast(@max(stat_.ino, 0)), - .mode = @truncate(@as(i64, @intCast(stat_.mode))), - .nlink = @truncate(@as(i64, @intCast(stat_.nlink))), - .uid = @truncate(@as(i64, @intCast(stat_.uid))), - .gid = @truncate(@as(i64, @intCast(stat_.gid))), - .rdev = @truncate(@as(i64, @intCast(stat_.rdev))), - .size = @truncate(@as(i64, @intCast(stat_.size))), - .blksize = @truncate(@as(i64, @intCast(stat_.blksize))), - .blocks = @truncate(@as(i64, @intCast(stat_.blocks))), - .atime_ms = toTimeMS(aTime), - .mtime_ms = toTimeMS(mTime), - .ctime_ms = toTimeMS(cTime), - .atime_ns = if (big) toNanoseconds(aTime) else 0, - .mtime_ns = if (big) toNanoseconds(mTime) else 0, - .ctime_ns = if (big) toNanoseconds(cTime) else 0, - - // Linux doesn't include this info in stat - // maybe it does in statx, but do you really need birthtime? If you do please file an issue. - .birthtime_ms = if (Environment.isLinux) 0 else toTimeMS(stat_.birthtime()), - .birthtime_ns = if (big and !Environment.isLinux) toNanoseconds(stat_.birthtime()) else 0, - }; - } - - pub fn constructor(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!*This { if (big) { - return globalObject.throwInvalidArguments("BigIntStats is not a constructor", .{}); + return Bun__createJSBigIntStatsObject( + globalObject, + dev, + ino, + mode, + nlink, + uid, + gid, + rdev, + size, + blksize, + blocks, + atime_ms, + mtime_ms, + ctime_ms, + birthtime_ms, + atime_ns, + mtime_ns, + ctime_ns, + birthtime_ns, + ); } - // dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeMs, mtimeMs, ctimeMs, birthtimeMs - var args = callFrame.arguments(); - - const atime_ms: f64 = if (args.len > 10 and args[10].isNumber()) args[10].asNumber() else 0; - const mtime_ms: f64 = if (args.len > 11 and args[11].isNumber()) args[11].asNumber() else 0; - const ctime_ms: f64 = if (args.len > 12 and args[12].isNumber()) args[12].asNumber() else 0; - const birthtime_ms: f64 = if (args.len > 13 and args[13].isNumber()) args[13].asNumber() else 0; - - const this = This.new(.{ - .dev = if (args.len > 0 and args[0].isNumber()) @intCast(args[0].toInt32()) else 0, - .mode = if (args.len > 1 and args[1].isNumber()) args[1].toInt32() else 0, - .nlink = if (args.len > 2 and args[2].isNumber()) args[2].toInt32() else 0, - .uid = if (args.len > 3 and args[3].isNumber()) args[3].toInt32() else 0, - .gid = if (args.len > 4 and args[4].isNumber()) args[4].toInt32() else 0, - .rdev = if (args.len > 5 and args[5].isNumber()) args[5].toInt32() else 0, - .blksize = if (args.len > 6 and args[6].isNumber()) args[6].toInt32() else 0, - .ino = if (args.len > 7 and args[7].isNumber()) @intCast(args[7].toInt32()) else 0, - .size = if (args.len > 8 and args[8].isNumber()) args[8].toInt32() else 0, - .blocks = if (args.len > 9 and args[9].isNumber()) args[9].toInt32() else 0, - .atime_ms = atime_ms, - .mtime_ms = mtime_ms, - .ctime_ms = ctime_ms, - .birthtime_ms = birthtime_ms, - }); - - return this; + return Bun__createJSStatsObject( + globalObject, + dev, + ino, + mode, + nlink, + uid, + gid, + rdev, + size, + blksize, + blocks, + atime_ms, + mtime_ms, + ctime_ms, + birthtime_ms, + ); } - comptime { - _ = isBlockDevice_WithoutTypeChecks; - _ = isCharacterDevice_WithoutTypeChecks; - _ = isDirectory_WithoutTypeChecks; - _ = isFIFO_WithoutTypeChecks; - _ = isFile_WithoutTypeChecks; - _ = isSocket_WithoutTypeChecks; - _ = isSymbolicLink_WithoutTypeChecks; + pub fn init(stat_: bun.Stat) @This() { + return @This(){ + .value = stat_, + }; } }; } +extern fn Bun__JSBigIntStatsObjectConstructor(*JSC.JSGlobalObject) JSC.JSValue; +extern fn Bun__JSStatsObjectConstructor(*JSC.JSGlobalObject) JSC.JSValue; + +extern fn Bun__createJSStatsObject( + globalObject: *JSC.JSGlobalObject, + dev: i64, + ino: i64, + mode: i64, + nlink: i64, + uid: i64, + gid: i64, + rdev: i64, + size: i64, + blksize: i64, + blocks: i64, + atimeMs: f64, + mtimeMs: f64, + ctimeMs: f64, + birthtimeMs: f64, +) JSC.JSValue; + +extern fn Bun__createJSBigIntStatsObject( + globalObject: *JSC.JSGlobalObject, + dev: i64, + ino: i64, + mode: i64, + nlink: i64, + uid: i64, + gid: i64, + rdev: i64, + size: i64, + blksize: i64, + blocks: i64, + atimeMs: i64, + mtimeMs: i64, + ctimeMs: i64, + birthtimeMs: i64, + atimeNs: u64, + mtimeNs: u64, + ctimeNs: u64, + birthtimeNs: u64, +) JSC.JSValue; pub const StatsSmall = StatType(false); pub const StatsBig = StatType(true); @@ -1921,8 +1798,8 @@ pub const Stats = union(enum) { pub fn toJSNewlyCreated(this: *const Stats, globalObject: *JSC.JSGlobalObject) JSC.JSValue { return switch (this.*) { - .big => StatsBig.new(this.big).toJS(globalObject), - .small => StatsSmall.new(this.small).toJS(globalObject), + .big => this.big.toJS(globalObject), + .small => this.small.toJS(globalObject), }; } @@ -1960,120 +1837,43 @@ pub const Dirent = struct { kind: Kind, pub const Kind = std.fs.File.Kind; - pub usingnamespace JSC.Codegen.JSDirent; - pub usingnamespace bun.New(@This()); - - pub fn constructor(global: *JSC.JSGlobalObject, call_frame: *JSC.CallFrame) bun.JSError!*Dirent { - const name_js, const type_js, const path_js = call_frame.argumentsAsArray(3); - - const name = try name_js.toBunString2(global); - errdefer name.deref(); - - const path = try path_js.toBunString2(global); - errdefer path.deref(); - - const kind = type_js.toInt32(); - const kind_enum: Kind = switch (kind) { - // these correspond to the libuv constants - else => .unknown, - 1 => .file, - 2 => .directory, - 3 => .sym_link, - 4 => .named_pipe, - 5 => .unix_domain_socket, - 6 => .character_device, - 7 => .block_device, - }; - - return Dirent.new(.{ - .name = name, - .path = path, - .kind = kind_enum, - }); - } - - pub fn toJS(this: *Dirent, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - const as_js = Dirent.toJSUnchecked(globalObject, this); - - // Immediately create JSString* objects for the name and path - // So that the GC is aware of them and can collect them if necessary - Dirent.nameSetCached(as_js, globalObject, this.name.toJS(globalObject)); - Dirent.pathSetCached(as_js, globalObject, this.path.toJS(globalObject)); - - return as_js; - } - - pub fn toJSNewlyCreated(this: *const Dirent, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - return toJS(Dirent.new(this.*), globalObject); - } - - pub fn getName(this: *Dirent, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - return this.name.toJS(globalObject); - } - pub fn getPath(this: *Dirent, globalThis: *JSC.JSGlobalObject) JSC.JSValue { - return this.path.toJS(globalThis); + extern fn Bun__JSDirentObjectConstructor(*JSC.JSGlobalObject) JSC.JSValue; + pub const getConstructor = Bun__JSDirentObjectConstructor; + + extern fn Bun__Dirent__toJS(*JSC.JSGlobalObject, i32, *bun.String, *bun.String, cached_previous_path_jsvalue: ?*?*JSC.JSString) JSC.JSValue; + pub fn toJS(this: *Dirent, globalObject: *JSC.JSGlobalObject, cached_previous_path_jsvalue: ?*?*JSC.JSString) JSC.JSValue { + return Bun__Dirent__toJS( + globalObject, + switch (this.kind) { + .file => bun.windows.libuv.UV_DIRENT_FILE, + .block_device => bun.windows.libuv.UV_DIRENT_BLOCK, + .character_device => bun.windows.libuv.UV_DIRENT_CHAR, + .directory => bun.windows.libuv.UV_DIRENT_DIR, + // event_port is deliberate there. + .event_port, .named_pipe => bun.windows.libuv.UV_DIRENT_FIFO, + + .unix_domain_socket => bun.windows.libuv.UV_DIRENT_SOCKET, + .sym_link => bun.windows.libuv.UV_DIRENT_LINK, + + .whiteout, .door, .unknown => bun.windows.libuv.UV_DIRENT_UNKNOWN, + }, + &this.name, + &this.path, + cached_previous_path_jsvalue, + ); } - pub fn isBlockDevice( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.block_device); - } - pub fn isCharacterDevice( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.character_device); - } - pub fn isDirectory( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.directory); - } - pub fn isFIFO( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.named_pipe or this.kind == std.fs.File.Kind.event_port); - } - pub fn isFile( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.file); - } - pub fn isSocket( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.unix_domain_socket); - } - pub fn isSymbolicLink( - this: *Dirent, - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - return JSC.JSValue.jsBoolean(this.kind == std.fs.File.Kind.sym_link); + pub fn toJSNewlyCreated(this: *Dirent, globalObject: *JSC.JSGlobalObject, previous_jsstring: ?*?*JSC.JSString) JSC.JSValue { + // Shouldn't techcnically be necessary. + defer this.deref(); + return this.toJS(globalObject, previous_jsstring); } pub fn deref(this: *const Dirent) void { this.name.deref(); this.path.deref(); } - - pub fn finalize(this: *Dirent) void { - this.deref(); - this.destroy(); - } }; pub const Process = struct { @@ -2332,7 +2132,7 @@ pub const Process = struct { comptime { if (Environment.export_cpp_apis and Environment.isWindows) { - @export(Bun__Process__editWindowsEnvVar, .{ .name = "Bun__Process__editWindowsEnvVar" }); + @export(&Bun__Process__editWindowsEnvVar, .{ .name = "Bun__Process__editWindowsEnvVar" }); } } @@ -2394,13 +2194,13 @@ pub fn StatFSType(comptime big: bool) type { pub usingnamespace bun.New(@This()); // Common fields between Linux and macOS - fstype: Int, - bsize: Int, - blocks: Int, - bfree: Int, - bavail: Int, - files: Int, - ffree: Int, + _fstype: Int, + _bsize: Int, + _blocks: Int, + _bfree: Int, + _bavail: Int, + _files: Int, + _ffree: Int, const This = @This(); @@ -2411,22 +2211,26 @@ pub fn StatFSType(comptime big: bool) type { pub fn callback(this: *This, globalObject: *JSC.JSGlobalObject) JSC.JSValue { const value = @field(this, @tagName(field)); const Type = @TypeOf(value); - if (comptime big and @typeInfo(Type) == .Int) { + if (comptime big and @typeInfo(Type) == .int) { return JSC.JSValue.fromInt64NoTruncate(globalObject, value); } - return JSC.JSValue.jsNumber(value); + const result = JSC.JSValue.jsDoubleNumber(@as(f64, @floatFromInt(value))); + if (Environment.isDebug) { + bun.assert_eql(result.asNumber(), @as(f64, @floatFromInt(value))); + } + return result; } }.callback; } - pub const fstype = getter(.fstype); - pub const bsize = getter(.bsize); - pub const blocks = getter(.blocks); - pub const bfree = getter(.bfree); - pub const bavail = getter(.bavail); - pub const files = getter(.files); - pub const ffree = getter(.ffree); + pub const fstype = getter(._fstype); + pub const bsize = getter(._bsize); + pub const blocks = getter(._blocks); + pub const bfree = getter(._bfree); + pub const bavail = getter(._bavail); + pub const files = getter(._files); + pub const ffree = getter(._ffree); pub fn finalize(this: *This) void { this.destroy(); @@ -2455,13 +2259,13 @@ pub fn StatFSType(comptime big: bool) type { else => @compileError("Unsupported OS"), }; return .{ - .fstype = @truncate(@as(i64, @intCast(fstype_))), - .bsize = @truncate(@as(i64, @intCast(bsize_))), - .blocks = @truncate(@as(i64, @intCast(blocks_))), - .bfree = @truncate(@as(i64, @intCast(bfree_))), - .bavail = @truncate(@as(i64, @intCast(bavail_))), - .files = @truncate(@as(i64, @intCast(files_))), - .ffree = @truncate(@as(i64, @intCast(ffree_))), + ._fstype = @truncate(@as(i64, @intCast(fstype_))), + ._bsize = @truncate(@as(i64, @intCast(bsize_))), + ._blocks = @truncate(@as(i64, @intCast(blocks_))), + ._bfree = @truncate(@as(i64, @intCast(bfree_))), + ._bavail = @truncate(@as(i64, @intCast(bavail_))), + ._files = @truncate(@as(i64, @intCast(files_))), + ._ffree = @truncate(@as(i64, @intCast(ffree_))), }; } @@ -2473,13 +2277,13 @@ pub fn StatFSType(comptime big: bool) type { var args = callFrame.arguments(); const this = This.new(.{ - .fstype = if (args.len > 0 and args[0].isNumber()) args[0].toInt32() else 0, - .bsize = if (args.len > 1 and args[1].isNumber()) args[1].toInt32() else 0, - .blocks = if (args.len > 2 and args[2].isNumber()) args[2].toInt32() else 0, - .bfree = if (args.len > 3 and args[3].isNumber()) args[3].toInt32() else 0, - .bavail = if (args.len > 4 and args[4].isNumber()) args[4].toInt32() else 0, - .files = if (args.len > 5 and args[5].isNumber()) args[5].toInt32() else 0, - .ffree = if (args.len > 6 and args[6].isNumber()) args[6].toInt32() else 0, + ._fstype = if (args.len > 0 and args[0].isNumber()) args[0].toInt32() else 0, + ._bsize = if (args.len > 1 and args[1].isNumber()) args[1].toInt32() else 0, + ._blocks = if (args.len > 2 and args[2].isNumber()) args[2].toInt32() else 0, + ._bfree = if (args.len > 3 and args[3].isNumber()) args[3].toInt32() else 0, + ._bavail = if (args.len > 4 and args[4].isNumber()) args[4].toInt32() else 0, + ._files = if (args.len > 5 and args[5].isNumber()) args[5].toInt32() else 0, + ._ffree = if (args.len > 6 and args[6].isNumber()) args[6].toInt32() else 0, }); return this; diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index 3c1e61e1601bbd..599873d157a145 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -65,7 +65,7 @@ const TokenKind = enum { option, @"option-terminator", - const COUNT = @typeInfo(TokenKind).Enum.fields.len; + const COUNT = @typeInfo(TokenKind).@"enum".fields.len; }; const Token = union(TokenKind) { positional: struct { index: u32, value: ValueRef }, @@ -652,7 +652,7 @@ pub fn parseArgs( comptime { const parseArgsFn = JSC.toJSHostFunction(parseArgs); - @export(parseArgsFn, .{ .name = "Bun__NodeUtil__jsParseArgs" }); + @export(&parseArgsFn, .{ .name = "Bun__NodeUtil__jsParseArgs" }); } pub fn parseArgsImpl(globalThis: *JSGlobalObject, config_obj: JSValue) bun.JSError!JSValue { diff --git a/src/bun.js/node/util/validators.zig b/src/bun.js/node/util/validators.zig index 699419a3cb7ea1..e6c003ef59da8c 100644 --- a/src/bun.js/node/util/validators.zig +++ b/src/bun.js/node/util/validators.zig @@ -19,7 +19,7 @@ pub fn throwErrInvalidArgValue( comptime fmt: [:0]const u8, args: anytype, ) bun.JSError { - @setCold(true); + @branchHint(.cold); return globalThis.ERR_INVALID_ARG_VALUE(fmt, args).throw(); } @@ -28,7 +28,7 @@ pub fn throwErrInvalidArgTypeWithMessage( comptime fmt: [:0]const u8, args: anytype, ) bun.JSError { - @setCold(true); + @branchHint(.cold); return globalThis.ERR_INVALID_ARG_TYPE(fmt, args).throw(); } @@ -39,7 +39,7 @@ pub fn throwErrInvalidArgType( comptime expected_type: []const u8, value: JSValue, ) bun.JSError { - @setCold(true); + @branchHint(.cold); const actual_type = getTypeName(globalThis, value); return throwErrInvalidArgTypeWithMessage(globalThis, "The \"" ++ name_fmt ++ "\" property must be of type {s}, got {s}", name_args ++ .{ expected_type, actual_type }); } @@ -49,7 +49,7 @@ pub fn throwRangeError( comptime fmt: [:0]const u8, args: anytype, ) bun.JSError { - @setCold(true); + @branchHint(.cold); return globalThis.ERR_OUT_OF_RANGE(fmt, args).throw(); } @@ -261,14 +261,14 @@ pub fn validateUndefined(globalThis: *JSGlobalObject, value: JSValue, comptime n pub fn validateStringEnum(comptime T: type, globalThis: *JSGlobalObject, value: JSValue, comptime name_fmt: string, name_args: anytype) bun.JSError!T { const str = try value.toBunString2(globalThis); defer str.deref(); - inline for (@typeInfo(T).Enum.fields) |enum_field| { + inline for (@typeInfo(T).@"enum".fields) |enum_field| { if (str.eqlComptime(enum_field.name)) return @field(T, enum_field.name); } const values_info = comptime blk: { var out: []const u8 = ""; - for (@typeInfo(T).Enum.fields, 0..) |enum_field, i| { + for (@typeInfo(T).@"enum".fields, 0..) |enum_field, i| { out = out ++ (if (i > 0) "|" else "") ++ enum_field.name; } break :blk out; diff --git a/src/bun.js/rare_data.zig b/src/bun.js/rare_data.zig index b63322b9a87e3c..1aa21cbdcabeb9 100644 --- a/src/bun.js/rare_data.zig +++ b/src/bun.js/rare_data.zig @@ -407,6 +407,28 @@ pub fn stdin(rare: *RareData) *Blob.Store { }; } +const StdinFdType = enum(i32) { + file = 0, + pipe = 1, + socket = 2, +}; + +pub export fn Bun__Process__getStdinFdType(vm: *JSC.VirtualMachine, fd: i32) StdinFdType { + const mode = switch (fd) { + 0 => vm.rareData().stdin().data.file.mode, + 1 => vm.rareData().stdout().data.file.mode, + 2 => vm.rareData().stderr().data.file.mode, + else => unreachable, + }; + if (bun.S.ISFIFO(mode)) { + return .pipe; + } else if (bun.S.ISSOCK(mode)) { + return .socket; + } else { + return .file; + } +} + const Subprocess = @import("./api/bun/subprocess.zig").Subprocess; pub fn spawnIPCContext(rare: *RareData, vm: *JSC.VirtualMachine) *uws.SocketContext { diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index 222aeeebabc8b0..f55568b2e3e27f 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -741,9 +741,9 @@ pub const Expect = struct { } } } else if (value.isStringLiteral() and expected.isStringLiteral()) { - const value_string = value.toSlice(globalThis, default_allocator); + const value_string = try value.toSlice(globalThis, default_allocator); defer value_string.deinit(); - const expected_string = expected.toSlice(globalThis, default_allocator); + const expected_string = try expected.toSlice(globalThis, default_allocator); defer expected_string.deinit(); if (expected_string.len == 0) { // edge case empty string is always contained @@ -2302,7 +2302,7 @@ pub const Expect = struct { // partial match const expected_slice = try expected_value.toSliceOrNull(globalThis); defer expected_slice.deinit(); - const received_slice = received_message.toSlice(globalThis, globalThis.allocator()); + const received_slice = try received_message.toSlice(globalThis, globalThis.allocator()); defer received_slice.deinit(); if (strings.contains(received_slice.slice(), expected_slice.slice())) return .undefined; } @@ -2546,14 +2546,17 @@ pub const Expect = struct { var hint = hint_string.toSlice(default_allocator); defer hint.deinit(); - const value: JSValue = try this.fnToErrStringOrUndefined(globalThis, try this.getValue(globalThis, thisValue, "toThrowErrorMatchingSnapshot", "properties, hint")); + const value: JSValue = (try this.fnToErrStringOrUndefined(globalThis, try this.getValue(globalThis, thisValue, "toThrowErrorMatchingSnapshot", "properties, hint"))) orelse { + const signature = comptime getSignature("toThrowErrorMatchingSnapshot", "", false); + return this.throw(globalThis, signature, "\n\nMatcher error: Received function did not throw\n", .{}); + }; return this.snapshot(globalThis, value, null, hint.slice(), "toThrowErrorMatchingSnapshot"); } - fn fnToErrStringOrUndefined(this: *Expect, globalThis: *JSGlobalObject, value: JSValue) !JSValue { + fn fnToErrStringOrUndefined(this: *Expect, globalThis: *JSGlobalObject, value: JSValue) !?JSValue { const err_value, _ = try this.getValueAsToThrow(globalThis, value); - var err_value_res = err_value orelse JSValue.undefined; + var err_value_res = err_value orelse return null; if (err_value_res.isAnyError()) { const message = try err_value_res.getTruthyComptime(globalThis, "message") orelse JSValue.undefined; err_value_res = message; @@ -2596,7 +2599,10 @@ pub const Expect = struct { const expected_slice: ?[]const u8 = if (has_expected) expected.slice() else null; - const value: JSValue = try this.fnToErrStringOrUndefined(globalThis, try this.getValue(globalThis, thisValue, "toThrowErrorMatchingInlineSnapshot", "properties, hint")); + const value: JSValue = (try this.fnToErrStringOrUndefined(globalThis, try this.getValue(globalThis, thisValue, "toThrowErrorMatchingInlineSnapshot", "properties, hint"))) orelse { + const signature = comptime getSignature("toThrowErrorMatchingInlineSnapshot", "", false); + return this.throw(globalThis, signature, "\n\nMatcher error: Received function did not throw\n", .{}); + }; return this.inlineSnapshot(globalThis, callFrame, value, null, expected_slice, "toThrowErrorMatchingInlineSnapshot"); } @@ -2652,6 +2658,77 @@ pub const Expect = struct { const value = try this.getValue(globalThis, thisValue, "toMatchInlineSnapshot", "properties, hint"); return this.inlineSnapshot(globalThis, callFrame, value, property_matchers, expected_slice, "toMatchInlineSnapshot"); } + const TrimResult = struct { trimmed: []const u8, start_indent: ?[]const u8, end_indent: ?[]const u8 }; + fn trimLeadingWhitespaceForInlineSnapshot(str_in: []const u8, trimmed_buf: []u8) TrimResult { + std.debug.assert(trimmed_buf.len == str_in.len); + var src = str_in; + var dst = trimmed_buf[0..]; + const give_up: TrimResult = .{ .trimmed = str_in, .start_indent = null, .end_indent = null }; + // if the line is all whitespace, trim fully + // the first line containing a character determines the max trim count + + // read first line (should be all-whitespace) + const first_newline = std.mem.indexOf(u8, src, "\n") orelse return give_up; + for (src[0..first_newline]) |char| if (char != ' ' and char != '\t') return give_up; + src = src[first_newline + 1 ..]; + + // read first real line and get indent + const indent_len = for (src, 0..) |char, i| { + if (char != ' ' and char != '\t') break i; + } else src.len; + if (indent_len == 0) return give_up; // no indent to trim; save time + const indent_str = src[0..indent_len]; + // we're committed now + dst[0] = '\n'; + dst = dst[1..]; + src = src[indent_len..]; + const second_newline = (std.mem.indexOf(u8, src, "\n") orelse return give_up) + 1; + @memcpy(dst[0..second_newline], src[0..second_newline]); + src = src[second_newline..]; + dst = dst[second_newline..]; + + while (src.len > 0) { + // try read indent + const max_indent_len = @min(src.len, indent_len); + const line_indent_len = for (src[0..max_indent_len], 0..) |char, i| { + if (char != ' ' and char != '\t') break i; + } else max_indent_len; + src = src[line_indent_len..]; + + if (line_indent_len < max_indent_len) { + if (src.len == 0) { + // perfect; done + break; + } + if (src[0] == '\n') { + // this line has less indentation than the first line, but it's empty so that's okay. + dst[0] = '\n'; + src = src[1..]; + dst = dst[1..]; + continue; + } + // this line had less indentation than the first line, but wasn't empty. give up. + return give_up; + } else { + // this line has the same or more indentation than the first line. copy it. + const line_newline = (std.mem.indexOf(u8, src, "\n") orelse { + // this is the last line. if it's not all whitespace, give up + for (src) |char| { + if (char != ' ' and char != '\t') return give_up; + } + break; + }) + 1; + @memcpy(dst[0..line_newline], src[0..line_newline]); + src = src[line_newline..]; + dst = dst[line_newline..]; + } + } + const end_indent = if (std.mem.lastIndexOfScalar(u8, str_in, '\n')) |c| c + 1 else return give_up; // there has to have been at least a single newline to get here + for (str_in[end_indent..]) |c| if (c != ' ' and c != 't') return give_up; // we already checked, but the last line is not all whitespace again + + // done + return .{ .trimmed = trimmed_buf[0 .. trimmed_buf.len - dst.len], .start_indent = indent_str, .end_indent = str_in[end_indent..] }; + } fn inlineSnapshot( this: *Expect, globalThis: *JSGlobalObject, @@ -2674,20 +2751,28 @@ pub const Expect = struct { defer pretty_value.deinit(); try this.matchAndFmtSnapshot(globalThis, value, property_matchers, &pretty_value, fn_name); + var start_indent: ?[]const u8 = null; + var end_indent: ?[]const u8 = null; if (result) |saved_value| { - if (strings.eqlLong(pretty_value.slice(), saved_value, true)) { + const buf = try Jest.runner.?.snapshots.allocator.alloc(u8, saved_value.len); + defer Jest.runner.?.snapshots.allocator.free(buf); + const trim_res = trimLeadingWhitespaceForInlineSnapshot(saved_value, buf); + + if (strings.eqlLong(pretty_value.slice(), trim_res.trimmed, true)) { Jest.runner.?.snapshots.passed += 1; return .undefined; } else if (update) { Jest.runner.?.snapshots.passed += 1; needs_write = true; + start_indent = trim_res.start_indent; + end_indent = trim_res.end_indent; } else { Jest.runner.?.snapshots.failed += 1; const signature = comptime getSignature(fn_name, "expected", false); const fmt = signature ++ "\n\n{any}\n"; const diff_format = DiffFormatter{ .received_string = pretty_value.slice(), - .expected_string = saved_value, + .expected_string = trim_res.trimmed, .globalThis = globalThis, }; @@ -2733,6 +2818,8 @@ pub const Expect = struct { .has_matchers = property_matchers != null, .is_added = result == null, .kind = fn_name, + .start_indent = if (start_indent) |ind| try Jest.runner.?.snapshots.allocator.dupe(u8, ind) else null, + .end_indent = if (end_indent) |ind| try Jest.runner.?.snapshots.allocator.dupe(u8, ind) else null, }); } @@ -3441,9 +3528,9 @@ pub const Expect = struct { var pass = value.isString() and expected.isString(); if (pass) { - const value_slice = value.toSlice(globalThis, default_allocator); + const value_slice = try value.toSlice(globalThis, default_allocator); defer value_slice.deinit(); - const expected_slice = expected.toSlice(globalThis, default_allocator); + const expected_slice = try expected.toSlice(globalThis, default_allocator); defer expected_slice.deinit(); const value_utf8 = value_slice.slice(); @@ -4609,7 +4696,7 @@ pub const Expect = struct { }; fn throwInvalidMatcherError(globalThis: *JSGlobalObject, matcher_name: bun.String, result: JSValue) bun.JSError { - @setCold(true); + @branchHint(.cold); var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalThis, @@ -4894,7 +4981,7 @@ pub const ExpectStatic = struct { } fn asyncChainingError(globalThis: *JSGlobalObject, flags: Expect.Flags, name: string) bun.JSError!JSValue { - @setCold(true); + @branchHint(.cold); const str = switch (flags.promise) { .resolves => "resolvesTo", .rejects => "rejectsTo", @@ -5423,7 +5510,7 @@ pub const ExpectMatcherUtils = struct { try buffered_writer.flush(); - return bun.String.createUTF8ForJS(globalThis, mutable_string.toOwnedSlice()); + return bun.String.createUTF8ForJS(globalThis, mutable_string.slice()); } inline fn printValueCatched(globalThis: *JSGlobalObject, value: JSValue, comptime color_or_null: ?[]const u8) JSValue { @@ -5532,9 +5619,9 @@ extern fn Expect__getPrototype(globalThis: *JSGlobalObject) JSValue; extern fn ExpectStatic__getPrototype(globalThis: *JSGlobalObject) JSValue; comptime { - @export(ExpectMatcherUtils.createSingleton, .{ .name = "ExpectMatcherUtils_createSigleton" }); - @export(Expect.readFlagsAndProcessPromise, .{ .name = "Expect_readFlagsAndProcessPromise" }); - @export(ExpectCustomAsymmetricMatcher.execute, .{ .name = "ExpectCustomAsymmetricMatcher__execute" }); + @export(&ExpectMatcherUtils.createSingleton, .{ .name = "ExpectMatcherUtils_createSigleton" }); + @export(&Expect.readFlagsAndProcessPromise, .{ .name = "Expect_readFlagsAndProcessPromise" }); + @export(&ExpectCustomAsymmetricMatcher.execute, .{ .name = "ExpectCustomAsymmetricMatcher__execute" }); } fn incrementExpectCallCounter() void { @@ -5542,3 +5629,113 @@ fn incrementExpectCallCounter() void { } const assert = bun.assert; + +fn testTrimLeadingWhitespaceForSnapshot(src: []const u8, expected: []const u8) !void { + const cpy = try std.testing.allocator.alloc(u8, src.len); + defer std.testing.allocator.free(cpy); + + const res = Expect.trimLeadingWhitespaceForInlineSnapshot(src, cpy); + sanityCheck(src, res); + + try std.testing.expectEqualStrings(expected, res.trimmed); +} +fn sanityCheck(input: []const u8, res: Expect.TrimResult) void { + // sanity check: output has same number of lines & all input lines endWith output lines + var input_iter = std.mem.splitScalar(u8, input, '\n'); + var output_iter = std.mem.splitScalar(u8, res.trimmed, '\n'); + while (true) { + const next_input = input_iter.next(); + const next_output = output_iter.next(); + if (next_input == null) { + std.debug.assert(next_output == null); + break; + } + std.debug.assert(next_output != null); + std.debug.assert(std.mem.endsWith(u8, next_input.?, next_output.?)); + } +} +fn testOne(input: []const u8) anyerror!void { + const cpy = try std.testing.allocator.alloc(u8, input.len); + defer std.testing.allocator.free(cpy); + const res = Expect.trimLeadingWhitespaceForInlineSnapshot(input, cpy); + sanityCheck(input, res); +} + +test "Expect.trimLeadingWhitespaceForInlineSnapshot" { + try testTrimLeadingWhitespaceForSnapshot( + \\ + \\Hello, world! + \\ + , + \\ + \\Hello, world! + \\ + ); + try testTrimLeadingWhitespaceForSnapshot( + \\ + \\ Hello, world! + \\ + , + \\ + \\Hello, world! + \\ + ); + try testTrimLeadingWhitespaceForSnapshot( + \\ + \\ Object{ + \\ key: value + \\ } + \\ + , + \\ + \\Object{ + \\ key: value + \\} + \\ + ); + try testTrimLeadingWhitespaceForSnapshot( + \\ + \\ Object{ + \\ key: value + \\ + \\ } + \\ + , + \\ + \\Object{ + \\key: value + \\ + \\} + \\ + ); + try testTrimLeadingWhitespaceForSnapshot( + \\ + \\ Object{ + \\ key: value + \\ } + \\ + , + \\ + \\ Object{ + \\ key: value + \\ } + \\ + ); + try testTrimLeadingWhitespaceForSnapshot( + \\ + \\ "æ™ + \\ + \\ !!!!*5897yhduN"'\`Il" + \\ + , + \\ + \\"æ™ + \\ + \\!!!!*5897yhduN"'\`Il" + \\ + ); +} + +test "fuzz Expect.trimLeadingWhitespaceForInlineSnapshot" { + try std.testing.fuzz(testOne, .{}); +} diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 3dcaacf0219334..137c286a0e6327 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -45,7 +45,6 @@ const CallFrame = JSC.CallFrame; const VirtualMachine = JSC.VirtualMachine; const Fs = bun.fs; -const is_bindgen: bool = false; const ArrayIdentityContext = bun.ArrayIdentityContext; @@ -132,12 +131,13 @@ pub const TestRunner = struct { pub fn scheduleTimeout(this: *TestRunner, milliseconds: u32) void { const then = bun.timespec.msFromNow(@intCast(milliseconds)); const vm = JSC.VirtualMachine.get(); + + this.event_loop_timer.tag = .TestRunner; if (this.event_loop_timer.state == .ACTIVE) { vm.timer.remove(&this.event_loop_timer); } this.event_loop_timer.next = then; - this.event_loop_timer.tag = .TestRunner; vm.timer.insert(&this.event_loop_timer); } @@ -528,7 +528,7 @@ pub const Jest = struct { if (arguments.len < 1 or !arguments[0].isString()) { return globalObject.throw("Bun.jest() expects a string filename", .{}); } - var str = arguments[0].toSlice(globalObject, bun.default_allocator); + var str = try arguments[0].toSlice(globalObject, bun.default_allocator); defer str.deinit(); const slice = str.slice(); @@ -559,10 +559,8 @@ pub const Jest = struct { } comptime { - if (!JSC.is_bindgen) { - @export(Bun__Jest__createTestModuleObject, .{ .name = "Bun__Jest__createTestModuleObject" }); - @export(Bun__Jest__createTestPreloadObject, .{ .name = "Bun__Jest__createTestPreloadObject" }); - } + @export(&Bun__Jest__createTestModuleObject, .{ .name = "Bun__Jest__createTestModuleObject" }); + @export(&Bun__Jest__createTestPreloadObject, .{ .name = "Bun__Jest__createTestPreloadObject" }); } }; @@ -592,6 +590,14 @@ pub const TestScope = struct { actual: u32 = 0, }; + pub fn deinit(this: *TestScope, globalThis: *JSGlobalObject) void { + if (this.label.len > 0) { + const label = this.label; + this.label = ""; + getAllocator(globalThis).free(label); + } + } + pub fn call(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSValue { return createScope(globalThis, callframe, "test()", true, .pass); } @@ -681,8 +687,6 @@ pub const TestScope = struct { this: *TestScope, task: *TestRunnerTask, ) Result { - if (comptime is_bindgen) return undefined; - var vm = VirtualMachine.get(); const func = this.func; defer { @@ -804,10 +808,10 @@ pub const TestScope = struct { pub const name = "TestScope"; pub const shim = JSC.Shimmer("Bun", name, @This()); comptime { - @export(jsOnResolve, .{ + @export(&jsOnResolve, .{ .name = shim.symbolName("onResolve"), }); - @export(jsOnReject, .{ + @export(&jsOnReject, .{ .name = shim.symbolName("onReject"), }); } @@ -816,10 +820,10 @@ pub const TestScope = struct { pub const DescribeScope = struct { label: string = "", parent: ?*DescribeScope = null, - beforeAll: std.ArrayListUnmanaged(JSValue) = .{}, - beforeEach: std.ArrayListUnmanaged(JSValue) = .{}, - afterEach: std.ArrayListUnmanaged(JSValue) = .{}, - afterAll: std.ArrayListUnmanaged(JSValue) = .{}, + beforeAlls: std.ArrayListUnmanaged(JSValue) = .{}, + beforeEachs: std.ArrayListUnmanaged(JSValue) = .{}, + afterEachs: std.ArrayListUnmanaged(JSValue) = .{}, + afterAlls: std.ArrayListUnmanaged(JSValue) = .{}, test_id_start: TestRunner.Test.ID = 0, test_id_len: TestRunner.Test.ID = 0, tests: std.ArrayListUnmanaged(TestScope) = .{}, @@ -858,7 +862,6 @@ pub const DescribeScope = struct { } pub fn push(new: *DescribeScope) void { - if (comptime is_bindgen) return; if (new.parent) |scope| { if (comptime Environment.allow_assert) { assert(DescribeScope.active != new); @@ -872,7 +875,6 @@ pub const DescribeScope = struct { } pub fn pop(this: *DescribeScope) void { - if (comptime is_bindgen) return; if (comptime Environment.allow_assert) assert(DescribeScope.active == this); DescribeScope.active = this.parent; } @@ -902,7 +904,7 @@ pub const DescribeScope = struct { } cb.protect(); - @field(DescribeScope.active.?, @tagName(hook)).append(getAllocator(globalThis), cb) catch unreachable; + @field(DescribeScope.active.?, @tagName(hook) ++ "s").append(getAllocator(globalThis), cb) catch unreachable; return JSValue.jsBoolean(true); } }.run; @@ -937,7 +939,7 @@ pub const DescribeScope = struct { pub const beforeEach = createCallback(.beforeEach); pub fn execCallback(this: *DescribeScope, globalObject: *JSGlobalObject, comptime hook: LifecycleHook) ?JSValue { - var hooks = &@field(this, @tagName(hook)); + var hooks = &@field(this, @tagName(hook) ++ "s"); defer { if (comptime hook == .beforeAll or hook == .afterAll) { hooks.clearAndFree(getAllocator(globalObject)); @@ -1098,7 +1100,6 @@ pub const DescribeScope = struct { } pub fn run(this: *DescribeScope, globalObject: *JSGlobalObject, callback: JSValue, args: []const JSValue) JSValue { - if (comptime is_bindgen) return undefined; callback.protect(); defer callback.unprotect(); this.push(); @@ -1157,8 +1158,7 @@ pub const DescribeScope = struct { Jest.runner.?.reportFailure(i + this.test_id_start, source.path.text, tests[i].label, 0, 0, this); i += 1; } - this.tests.clearAndFree(allocator); - this.pending_tests.deinit(allocator); + this.deinit(globalObject); return; } if (end == 0) { @@ -1217,9 +1217,23 @@ pub const DescribeScope = struct { _ = globalThis.bunVM().uncaughtException(globalThis, err, true); } } + this.deinit(globalThis); + } - this.pending_tests.deinit(getAllocator(globalThis)); - this.tests.clearAndFree(getAllocator(globalThis)); + pub fn deinit(this: *DescribeScope, globalThis: *JSGlobalObject) void { + const allocator = getAllocator(globalThis); + + if (this.label.len > 0) { + const label = this.label; + this.label = ""; + allocator.free(label); + } + + this.pending_tests.deinit(allocator); + for (this.tests.items) |*t| { + t.deinit(globalThis); + } + this.tests.clearAndFree(allocator); } const ScopeStack = ObjectPool(std.ArrayListUnmanaged(*DescribeScope), null, true, 16); @@ -1750,11 +1764,15 @@ inline fn createScope( const parent = DescribeScope.active.?; const allocator = getAllocator(globalThis); - const label = if (description == .zero) - "" - else - (description.toSlice(globalThis, allocator).cloneIfNeeded(allocator) catch unreachable).slice(); - + const label = brk: { + if (description == .zero) { + break :brk ""; + } else { + var slice = try description.toSlice(globalThis, allocator); + defer slice.deinit(); + break :brk try allocator.dupe(u8, slice.slice()); + } + }; var tag_to_use = tag; if (tag_to_use == .only or parent.tag == .only) { @@ -2057,11 +2075,17 @@ fn eachBind(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSVa item.protect(); function_args[0] = item; } - - const label = if (description.isEmptyOrUndefinedOrNull()) - "" - else - (description.toSlice(globalThis, allocator).cloneIfNeeded(allocator) catch unreachable).slice(); + var _label: ?JSC.ZigString.Slice = null; + defer if (_label) |slice| slice.deinit(); + const label = brk: { + if (description.isEmptyOrUndefinedOrNull()) { + break :brk ""; + } else { + _label = try description.toSlice(globalThis, allocator); + break :brk _label.?.slice(); + } + }; + // this returns a owned slice const formattedLabel = try formatLabel(globalThis, label, function_args, test_idx); const tag = parent.tag; @@ -2086,6 +2110,8 @@ fn eachBind(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSVa if (is_skip) { parent.skip_count += 1; function.unprotect(); + // lets free the formatted label + allocator.free(formattedLabel); } else if (each_data.is_test) { if (Jest.runner.?.only and tag != .only) { return .undefined; diff --git a/src/bun.js/test/pretty_format.zig b/src/bun.js/test/pretty_format.zig index ac9b1fdcd72a27..5d7fd28884c31b 100644 --- a/src/bun.js/test/pretty_format.zig +++ b/src/bun.js/test/pretty_format.zig @@ -4,7 +4,6 @@ const Output = bun.Output; const JSC = bun.JSC; const JSGlobalObject = JSC.JSGlobalObject; const JSValue = JSC.JSValue; -const is_bindgen: bool = false; const default_allocator = bun.default_allocator; const CAPI = JSC.C; const ZigString = JSC.ZigString; @@ -13,7 +12,6 @@ const string = bun.string; const JSLexer = bun.js_lexer; const JSPrinter = bun.js_printer; const JSPrivateDataPtr = JSC.JSPrivateDataPtr; -const JS = @import("../javascript.zig"); const JSPromise = JSC.JSPromise; const expect = @import("./expect.zig"); @@ -933,7 +931,7 @@ pub const JestPrettyFormat = struct { switch (comptime Format) { .StringPossiblyFormatted => { - var str = value.toSlice(this.globalThis, bun.default_allocator); + var str = try value.toSlice(this.globalThis, bun.default_allocator); defer str.deinit(); this.addForNewLine(str.len); const slice = str.slice(); @@ -1979,9 +1977,6 @@ pub const JestPrettyFormat = struct { } pub fn format(this: *JestPrettyFormat.Formatter, result: Tag.Result, comptime Writer: type, writer: Writer, value: JSValue, globalThis: *JSGlobalObject, comptime enable_ansi_colors: bool) bun.JSError!void { - if (comptime is_bindgen) { - return; - } const prevGlobalThis = this.globalThis; defer this.globalThis = prevGlobalThis; this.globalThis = globalThis; @@ -1990,7 +1985,7 @@ pub const JestPrettyFormat = struct { // comptime var so we have to repeat it here. The rationale there is // it _should_ limit the stack usage because each version of the // function will be relatively small - return try switch (result.tag) { + return switch (result.tag) { .StringPossiblyFormatted => this.printAs(.StringPossiblyFormatted, Writer, writer, value, result.cell, enable_ansi_colors), .String => this.printAs(.String, Writer, writer, value, result.cell, enable_ansi_colors), .Undefined => this.printAs(.Undefined, Writer, writer, value, result.cell, enable_ansi_colors), diff --git a/src/bun.js/test/snapshot.zig b/src/bun.js/test/snapshot.zig index b9380d4f68b014..becdc040399807 100644 --- a/src/bun.js/test/snapshot.zig +++ b/src/bun.js/test/snapshot.zig @@ -41,6 +41,8 @@ pub const Snapshots = struct { has_matchers: bool, is_added: bool, kind: []const u8, // static lifetime + start_indent: ?[]const u8, // owned by Snapshots.allocator + end_indent: ?[]const u8, // owned by Snapshots.allocator fn lessThanFn(_: void, a: InlineSnapshotToWrite, b: InlineSnapshotToWrite) bool { if (a.line < b.line) return true; @@ -298,7 +300,7 @@ pub const Snapshots = struct { }; const fn_name = ils.kind; if (!bun.strings.startsWith(file_text[next_start..], fn_name)) { - try log.addErrorFmt(&source, .{ .start = @intCast(next_start) }, arena, "Failed to update inline snapshot: Could not find 'toMatchInlineSnapshot' here", .{}); + try log.addErrorFmt(&source, .{ .start = @intCast(next_start) }, arena, "Failed to update inline snapshot: Could not find '{s}' here", .{fn_name}); continue; } next_start += fn_name.len; @@ -395,10 +397,49 @@ pub const Snapshots = struct { try result_text.appendSlice(file_text[uncommitted_segment_end..final_start_usize]); uncommitted_segment_end = final_end_usize; + // preserve existing indentation level, otherwise indent the same as the start position plus two spaces + var needs_more_spaces = false; + const start_indent = ils.start_indent orelse D: { + const source_until_final_start = source.contents[0..final_start_usize]; + const line_start = if (std.mem.lastIndexOfScalar(u8, source_until_final_start, '\n')) |newline_loc| newline_loc + 1 else 0; + const indent_count = for (source_until_final_start[line_start..], 0..) |char, j| { + if (char != ' ' and char != '\t') break j; + } else source_until_final_start[line_start..].len; + needs_more_spaces = true; + break :D source_until_final_start[line_start..][0..indent_count]; + }; + + var re_indented_string = std.ArrayList(u8).init(arena); + defer re_indented_string.deinit(); + const re_indented = if (ils.value.len > 0 and ils.value[0] == '\n') blk: { + // append starting newline + try re_indented_string.appendSlice("\n"); + var re_indented_source = ils.value[1..]; + while (re_indented_source.len > 0) { + const next_newline = if (std.mem.indexOfScalar(u8, re_indented_source, '\n')) |a| a + 1 else re_indented_source.len; + const segment = re_indented_source[0..next_newline]; + if (segment.len == 0) { + // last line; loop already exited + unreachable; + } else if (bun.strings.eqlComptime(segment, "\n")) { + // zero length line. no indent. + } else { + // regular line. indent. + try re_indented_string.appendSlice(start_indent); + if (needs_more_spaces) try re_indented_string.appendSlice(" "); + } + try re_indented_string.appendSlice(segment); + re_indented_source = re_indented_source[next_newline..]; + } + // indent before backtick + try re_indented_string.appendSlice(ils.end_indent orelse start_indent); + break :blk re_indented_string.items; + } else ils.value; + if (needs_pre_comma) try result_text.appendSlice(", "); const result_text_writer = result_text.writer(); try result_text.appendSlice("`"); - try bun.js_printer.writePreQuotedString(ils.value, @TypeOf(result_text_writer), result_text_writer, '`', false, false, .utf8); + try bun.js_printer.writePreQuotedString(re_indented, @TypeOf(result_text_writer), result_text_writer, '`', false, false, .utf8); try result_text.appendSlice("`"); if (ils.is_added) Jest.runner.?.snapshots.added += 1; @@ -469,7 +510,7 @@ pub const Snapshots = struct { remain[0] = 0; const snapshot_file_path = snapshot_file_path_buf[0 .. snapshot_file_path_buf.len - remain.len :0]; - var flags: bun.Mode = bun.O.CREAT | bun.O.RDWR; + var flags: i32 = bun.O.CREAT | bun.O.RDWR; if (this.update_snapshots) flags |= bun.O.TRUNC; const fd = switch (bun.sys.open(snapshot_file_path, flags, 0o644)) { .result => |_fd| _fd, diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index c8ae517d906542..3cd99e7ebe907d 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -535,12 +535,10 @@ pub const WebWorker = struct { } comptime { - if (!JSC.is_bindgen) { - @export(create, .{ .name = "WebWorker__create" }); - @export(requestTerminate, .{ .name = "WebWorker__requestTerminate" }); - @export(setRef, .{ .name = "WebWorker__setRef" }); - _ = WebWorker__updatePtr; - } + @export(&create, .{ .name = "WebWorker__create" }); + @export(&requestTerminate, .{ .name = "WebWorker__requestTerminate" }); + @export(&setRef, .{ .name = "WebWorker__setRef" }); + _ = WebWorker__updatePtr; } }; diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig index 36446d2dceee1f..ab76f70729daf9 100644 --- a/src/bun.js/webcore.zig +++ b/src/bun.js/webcore.zig @@ -34,7 +34,7 @@ fn alert(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSErr if (has_message) { var state = std.heap.stackFallback(2048, bun.default_allocator); const allocator = state.get(); - const message = arguments[0].toSlice(globalObject, allocator); + const message = try arguments[0].toSlice(globalObject, allocator); defer message.deinit(); if (message.len > 0) { @@ -88,7 +88,7 @@ fn confirm(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE // 3. Set message to the result of optionally truncating message. // * Not necessary so we won't do it. - const message = arguments[0].toSlice(globalObject, allocator); + const message = try arguments[0].toSlice(globalObject, allocator); defer message.deinit(); output.writeAll(message.slice()) catch { @@ -230,7 +230,7 @@ pub const Prompt = struct { // 3. Set message to the result of optionally truncating message. // * Not necessary so we won't do it. - const message = arguments[0].toSlice(globalObject, allocator); + const message = try arguments[0].toSlice(globalObject, allocator); defer message.deinit(); output.writeAll(message.slice()) catch { @@ -251,7 +251,7 @@ pub const Prompt = struct { }; if (has_default) { - const default_string = arguments[1].toSlice(globalObject, allocator); + const default_string = try arguments[1].toSlice(globalObject, allocator); defer default_string.deinit(); output.print("[{s}] ", .{default_string.slice()}) catch { @@ -533,7 +533,7 @@ pub const Crypto = struct { return globalThis.ERR_CRYPTO_SCRYPT_INVALID_PARAMETER("Invalid scrypt parameters", .{}).throw(); } - fn throwInvalidParams(globalThis: *JSC.JSGlobalObject, comptime error_type: @Type(.EnumLiteral), comptime message: [:0]const u8, fmt: anytype) bun.JSError { + fn throwInvalidParams(globalThis: *JSC.JSGlobalObject, comptime error_type: @Type(.enum_literal), comptime message: [:0]const u8, fmt: anytype) bun.JSError { if (error_type != .RangeError) @compileError("Error type not added!"); BoringSSL.ERR_clear_error(); return globalThis.ERR_CRYPTO_INVALID_SCRYPT_PARAMS(message, fmt).throw(); @@ -644,7 +644,7 @@ pub const Crypto = struct { comptime { const Bun__randomUUIDv7 = JSC.toJSHostFunction(Bun__randomUUIDv7_); - @export(Bun__randomUUIDv7, .{ .name = "Bun__randomUUIDv7" }); + @export(&Bun__randomUUIDv7, .{ .name = "Bun__randomUUIDv7" }); } pub fn Bun__randomUUIDv7_(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.argumentsUndef(2).slice(); @@ -730,19 +730,15 @@ pub const Crypto = struct { pub usingnamespace JSC.Codegen.JSCrypto; comptime { - if (!JSC.is_bindgen) { - _ = CryptoObject__create; - } + _ = CryptoObject__create; } }; comptime { - if (!JSC.is_bindgen) { - const js_alert = JSC.toJSHostFunction(alert); - @export(js_alert, .{ .name = "WebCore__alert" }); - const js_prompt = JSC.toJSHostFunction(Prompt.call); - @export(js_prompt, .{ .name = "WebCore__prompt" }); - const js_confirm = JSC.toJSHostFunction(confirm); - @export(js_confirm, .{ .name = "WebCore__confirm" }); - } + const js_alert = JSC.toJSHostFunction(alert); + @export(&js_alert, .{ .name = "WebCore__alert" }); + const js_prompt = JSC.toJSHostFunction(Prompt.call); + @export(&js_prompt, .{ .name = "WebCore__prompt" }); + const js_confirm = JSC.toJSHostFunction(confirm); + @export(&js_confirm, .{ .name = "WebCore__confirm" }); } diff --git a/src/bun.js/webcore/ObjectURLRegistry.zig b/src/bun.js/webcore/ObjectURLRegistry.zig index 5bf2ed7803e868..65234b632a703f 100644 --- a/src/bun.js/webcore/ObjectURLRegistry.zig +++ b/src/bun.js/webcore/ObjectURLRegistry.zig @@ -91,7 +91,7 @@ pub fn has(this: *ObjectURLRegistry, pathname: []const u8) bool { comptime { const Bun__createObjectURL = JSC.toJSHostFunction(Bun__createObjectURL_); - @export(Bun__createObjectURL, .{ .name = "Bun__createObjectURL" }); + @export(&Bun__createObjectURL, .{ .name = "Bun__createObjectURL" }); } fn Bun__createObjectURL_(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.arguments_old(1); @@ -109,7 +109,7 @@ fn Bun__createObjectURL_(globalObject: *JSC.JSGlobalObject, callframe: *JSC.Call comptime { const Bun__revokeObjectURL = JSC.toJSHostFunction(Bun__revokeObjectURL_); - @export(Bun__revokeObjectURL, .{ .name = "Bun__revokeObjectURL" }); + @export(&Bun__revokeObjectURL, .{ .name = "Bun__revokeObjectURL" }); } fn Bun__revokeObjectURL_(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.arguments_old(1); @@ -138,7 +138,7 @@ fn Bun__revokeObjectURL_(globalObject: *JSC.JSGlobalObject, callframe: *JSC.Call comptime { const jsFunctionResolveObjectURL = JSC.toJSHostFunction(jsFunctionResolveObjectURL_); - @export(jsFunctionResolveObjectURL, .{ .name = "jsFunctionResolveObjectURL" }); + @export(&jsFunctionResolveObjectURL, .{ .name = "jsFunctionResolveObjectURL" }); } fn jsFunctionResolveObjectURL_(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.arguments_old(1); diff --git a/src/bun.js/webcore/S3File.zig b/src/bun.js/webcore/S3File.zig index 6502d13a0e7450..8309c0fe8885a0 100644 --- a/src/bun.js/webcore/S3File.zig +++ b/src/bun.js/webcore/S3File.zig @@ -251,7 +251,7 @@ pub fn constructS3FileWithS3CredentialsAndOptions( inner: { if (file_type.isString()) { var allocator = bun.default_allocator; - var str = file_type.toSlice(globalObject, bun.default_allocator); + var str = try file_type.toSlice(globalObject, bun.default_allocator); defer str.deinit(); const slice = str.slice(); if (!strings.isAllASCII(slice)) { @@ -294,7 +294,7 @@ pub fn constructS3FileWithS3Credentials( inner: { if (file_type.isString()) { var allocator = bun.default_allocator; - var str = file_type.toSlice(globalObject, bun.default_allocator); + var str = try file_type.toSlice(globalObject, bun.default_allocator); defer str.deinit(); const slice = str.slice(); if (!strings.isAllASCII(slice)) { @@ -475,8 +475,7 @@ pub fn getPresignUrlFrom(this: *Blob, globalThis: *JSC.JSGlobalObject, extra_opt return S3.throwSignError(sign_err, globalThis); }; defer result.deinit(); - var str = bun.String.fromUTF8(result.url); - return str.transferToJS(this.globalThis); + return bun.String.createUTF8ForJS(this.globalThis, result.url); } pub fn getBucketName( this: *const Blob, @@ -604,11 +603,11 @@ pub fn hasInstance(_: JSC.JSValue, _: *JSC.JSGlobalObject, value: JSC.JSValue) c } comptime { - @export(exports.JSS3File__presign, .{ .name = "JSS3File__presign" }); - @export(construct, .{ .name = "JSS3File__construct" }); - @export(hasInstance, .{ .name = "JSS3File__hasInstance" }); - @export(getBucket, .{ .name = "JSS3File__bucket" }); - @export(getStat, .{ .name = "JSS3File__stat" }); + @export(&exports.JSS3File__presign, .{ .name = "JSS3File__presign" }); + @export(&construct, .{ .name = "JSS3File__construct" }); + @export(&hasInstance, .{ .name = "JSS3File__hasInstance" }); + @export(&getBucket, .{ .name = "JSS3File__bucket" }); + @export(&getStat, .{ .name = "JSS3File__stat" }); } pub const exports = struct { diff --git a/src/bun.js/webcore/S3Stat.zig b/src/bun.js/webcore/S3Stat.zig index 53deb25bcb4c94..361c639d3f2150 100644 --- a/src/bun.js/webcore/S3Stat.zig +++ b/src/bun.js/webcore/S3Stat.zig @@ -1,5 +1,5 @@ -const bun = @import("../../bun.zig"); -const JSC = @import("../../jsc.zig"); +const bun = @import("root").bun; +const JSC = bun.JSC; pub const S3Stat = struct { const log = bun.Output.scoped(.S3Stat, false); diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index 1d7e0a1c6d8dba..9b29a52dce8e02 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -49,9 +49,6 @@ const PathOrBlob = JSC.Node.PathOrBlob; const WriteFilePromise = @import("./blob/WriteFile.zig").WriteFilePromise; const WriteFileWaitFromLockedValueTask = @import("./blob/WriteFile.zig").WriteFileWaitFromLockedValueTask; const NewReadFileHandler = @import("./blob/ReadFile.zig").NewReadFileHandler; -const WriteFile = @import("./blob/WriteFile.zig").WriteFile; -const ReadFile = @import("./blob/ReadFile.zig").ReadFile; -const WriteFileWindows = @import("./blob/WriteFile.zig").WriteFileWindows; const S3File = @import("./S3File.zig"); @@ -60,8 +57,20 @@ pub const Blob = struct { pub usingnamespace bun.New(@This()); pub usingnamespace JSC.Codegen.JSBlob; - pub usingnamespace @import("./blob/WriteFile.zig"); - pub usingnamespace @import("./blob/ReadFile.zig"); + + // pub usingnamespace @import("./blob/ReadFile.zig"); + const rf = @import("./blob/ReadFile.zig"); + pub const ReadFile = rf.ReadFile; + pub const ReadFileUV = rf.ReadFileUV; + pub const ReadFileTask = rf.ReadFileTask; + pub const ReadFileResultType = rf.ReadFileResultType; + + // pub usingnamespace @import("./blob/WriteFile.zig"); + const wf = @import("./blob/WriteFile.zig"); + pub const WriteFile = wf.WriteFile; + pub const WriteFileWindows = wf.WriteFileWindows; + pub const WriteFileTask = wf.WriteFileTask; + pub const ClosingState = enum(u8) { running, closing, @@ -142,7 +151,6 @@ pub const Blob = struct { return store.data == .file; } - const ReadFileUV = @import("./blob/ReadFile.zig").ReadFileUV; pub fn doReadFromS3(this: *Blob, comptime Function: anytype, global: *JSGlobalObject) JSValue { bloblog("doReadFromS3", .{}); @@ -183,7 +191,7 @@ pub const Blob = struct { handler, Handler.run, ) catch bun.outOfMemory(); - var read_file_task = ReadFile.ReadFileTask.createOnJSThread(bun.default_allocator, global, file_read) catch bun.outOfMemory(); + var read_file_task = ReadFileTask.createOnJSThread(bun.default_allocator, global, file_read) catch bun.outOfMemory(); // Create the Promise only after the store has been ref()'d. // The garbage collector runs on memory allocations @@ -202,7 +210,7 @@ pub const Blob = struct { pub fn NewInternalReadFileHandler(comptime Context: type, comptime Function: anytype) type { return struct { - pub fn run(handler: *anyopaque, bytes_: ReadFile.ResultType) void { + pub fn run(handler: *anyopaque, bytes_: ReadFileResultType) void { Function(bun.cast(Context, handler), bytes_); } }; @@ -221,7 +229,7 @@ pub const Blob = struct { this.offset, this.size, ) catch bun.outOfMemory(); - var read_file_task = ReadFile.ReadFileTask.createOnJSThread(bun.default_allocator, global, file_read) catch bun.outOfMemory(); + var read_file_task = ReadFileTask.createOnJSThread(bun.default_allocator, global, file_read) catch bun.outOfMemory(); read_file_task.schedule(); } @@ -604,7 +612,7 @@ pub const Blob = struct { const store = Blob.Store.init(context.joiner.done(allocator) catch bun.outOfMemory(), allocator); var blob = Blob.initWithStore(store, globalThis); - blob.content_type = std.fmt.allocPrint(allocator, "multipart/form-data; boundary=\"{s}\"", .{boundary}) catch bun.outOfMemory(); + blob.content_type = std.fmt.allocPrint(allocator, "multipart/form-data; boundary={s}", .{boundary}) catch bun.outOfMemory(); blob.content_type_allocated = true; blob.content_type_was_set = true; @@ -973,7 +981,7 @@ pub const Blob = struct { WriteFilePromise.run, options.mkdirp_if_not_exists orelse true, ) catch unreachable; - var task = WriteFile.WriteFileTask.createOnJSThread(bun.default_allocator, ctx, file_copier) catch bun.outOfMemory(); + var task = WriteFileTask.createOnJSThread(bun.default_allocator, ctx, file_copier) catch bun.outOfMemory(); // Defer promise creation until we're just about to schedule the task var promise = JSC.JSPromise.create(ctx); const promise_value = promise.asValue(ctx); @@ -1697,7 +1705,7 @@ pub const Blob = struct { if (try options.get(globalThis, "type")) |content_type| { inner: { if (content_type.isString()) { - var content_type_str = content_type.toSlice(globalThis, bun.default_allocator); + var content_type_str = try content_type.toSlice(globalThis, bun.default_allocator); defer content_type_str.deinit(); const slice = content_type_str.slice(); if (!strings.isAllASCII(slice)) { @@ -1799,7 +1807,7 @@ pub const Blob = struct { inner: { if (file_type.isString()) { var allocator = bun.default_allocator; - var str = file_type.toSlice(globalObject, bun.default_allocator); + var str = try file_type.toSlice(globalObject, bun.default_allocator); defer str.deinit(); const slice = str.slice(); if (!strings.isAllASCII(slice)) { @@ -2294,10 +2302,7 @@ pub const Blob = struct { this.update(); } - pub fn doClose( - this: *This, - is_allowed_to_close_fd: bool, - ) bool { + pub fn doClose(this: *This, is_allowed_to_close_fd: bool) bool { if (@hasField(This, "io_request")) { if (this.close_after_io) { this.state.store(ClosingState.closing, .seq_cst); @@ -2827,7 +2832,7 @@ pub const Blob = struct { fn truncate(this: *CopyFileWindows) void { // TODO: optimize this - @setCold(true); + @branchHint(.cold); var node_fs: JSC.Node.NodeFS = .{}; _ = node_fs.truncate( @@ -2903,6 +2908,9 @@ pub const Blob = struct { .syscall = bun.String.static("fstat"), }; + pub const CopyFilePromiseTask = JSC.ConcurrentPromiseTask(CopyFile); + pub const CopyFilePromiseTaskEventLoopTask = CopyFilePromiseTask.EventLoopTask; + // blocking, but off the main thread pub const CopyFile = struct { destination_file_store: FileStore, @@ -2927,8 +2935,6 @@ pub const Blob = struct { pub const ResultType = anyerror!SizeType; pub const Callback = *const fn (ctx: *anyopaque, len: ResultType) void; - pub const CopyFilePromiseTask = JSC.ConcurrentPromiseTask(CopyFile); - pub const CopyFilePromiseTaskEventLoopTask = CopyFilePromiseTask.EventLoopTask; pub fn create( allocator: std.mem.Allocator, @@ -3234,7 +3240,7 @@ pub const Blob = struct { } pub fn doFCopyFileWithReadWriteLoopFallback(this: *CopyFile) anyerror!void { - switch (bun.sys.fcopyfile(this.source_fd, this.destination_fd, posix.system.COPYFILE_DATA)) { + switch (bun.sys.fcopyfile(this.source_fd, this.destination_fd, posix.system.COPYFILE{ .DATA = true })) { .err => |errno| { switch (errno.getErrno()) { // If the file type doesn't support seeking, it may return EBADF @@ -3293,6 +3299,7 @@ pub const Blob = struct { } pub fn runAsync(this: *CopyFile) void { + if (Environment.isWindows) return; //why // defer task.onFinish(); var stat_: ?bun.Stat = null; @@ -3482,10 +3489,15 @@ pub const Blob = struct { // milliseconds since ECMAScript epoch last_modified: JSC.JSTimeType = JSC.init_timestamp, - pub fn unlink(this: *const FileStore, globalThis: *JSC.JSGlobalObject) JSValue { + pub fn unlink(this: *const FileStore, globalThis: *JSC.JSGlobalObject) bun.JSError!JSValue { return switch (this.pathlike) { .path => |path_like| JSC.Node.Async.unlink.create(globalThis, undefined, .{ - .path = .{ .encoded_slice = ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator) }, + .path = .{ + .encoded_slice = switch (path_like) { + .encoded_slice => |slice| try slice.toOwned(bun.default_allocator), + else => try ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator), + }, + }, }, globalThis.bunVM()), .fd => JSC.JSPromise.resolvedPromiseValue(globalThis, globalThis.createInvalidArgs("Is not possible to unlink a file descriptor", .{})), }; @@ -3978,7 +3990,7 @@ pub const Blob = struct { if (!content_type.isString()) { return globalThis.throwInvalidArgumentType("write", "options.type", "string"); } - var content_type_str = content_type.toSlice(globalThis, bun.default_allocator); + var content_type_str = try content_type.toSlice(globalThis, bun.default_allocator); defer content_type_str.deinit(); const slice = content_type_str.slice(); if (strings.isAllASCII(slice)) { @@ -4083,9 +4095,9 @@ pub const Blob = struct { }); comptime { const jsonResolveRequestStream = JSC.toJSHostFunction(onFileStreamResolveRequestStream); - @export(jsonResolveRequestStream, .{ .name = Export[0].symbol_name }); + @export(&jsonResolveRequestStream, .{ .name = Export[0].symbol_name }); const jsonRejectRequestStream = JSC.toJSHostFunction(onFileStreamRejectRequestStream); - @export(jsonRejectRequestStream, .{ .name = Export[1].symbol_name }); + @export(&jsonRejectRequestStream, .{ .name = Export[1].symbol_name }); } pub fn pipeReadableStreamToBlob(this: *Blob, globalThis: *JSC.JSGlobalObject, readable_stream: JSC.WebCore.ReadableStream, extra_options: ?JSValue) JSC.JSValue { var store = this.store orelse { @@ -4322,7 +4334,7 @@ pub const Blob = struct { if (!content_type.isString()) { return globalThis.throwInvalidArgumentType("write", "options.type", "string"); } - var content_type_str = content_type.toSlice(globalThis, bun.default_allocator); + var content_type_str = try content_type.toSlice(globalThis, bun.default_allocator); defer content_type_str.deinit(); const slice = content_type_str.slice(); if (strings.isAllASCII(slice)) { @@ -4741,19 +4753,25 @@ pub const Blob = struct { } comptime { - if (!JSC.is_bindgen) { - _ = Bun__Blob__getSizeForBindings; - } + _ = Bun__Blob__getSizeForBindings; } - pub fn getStat(this: *Blob, globalThis: *JSC.JSGlobalObject, callback: *JSC.CallFrame) JSC.JSValue { + pub fn getStat(this: *Blob, globalThis: *JSC.JSGlobalObject, callback: *JSC.CallFrame) bun.JSError!JSC.JSValue { const store = this.store orelse return JSC.JSValue.jsUndefined(); // TODO: make this async for files return switch (store.data) { .file => |*file| { return switch (file.pathlike) { - .path => |path_like| JSC.Node.Async.stat.create(globalThis, undefined, .{ - .path = .{ .encoded_slice = ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator) }, - }, globalThis.bunVM()), + .path => |path_like| { + return JSC.Node.Async.stat.create(globalThis, undefined, .{ + .path = .{ + .encoded_slice = switch (path_like) { + // it's already converted to utf8 + .encoded_slice => |slice| try slice.toOwned(bun.default_allocator), + else => try ZigString.init(path_like.slice()).toSliceClone(bun.default_allocator), + }, + }, + }, globalThis.bunVM()); + }, .fd => |fd| JSC.Node.Async.fstat.create(globalThis, undefined, .{ .fd = fd }, globalThis.bunVM()), }; }, @@ -4826,7 +4844,7 @@ pub const Blob = struct { Blob.max_size; store.data.file.mode = @intCast(stat.mode); store.data.file.seekable = bun.isRegularFile(stat.mode); - store.data.file.last_modified = JSC.toJSTime(stat.mtime().tv_sec, stat.mtime().tv_nsec); + store.data.file.last_modified = JSC.toJSTime(stat.mtime().sec, stat.mtime().nsec); }, // the file may not exist yet. Thats's okay. else => {}, @@ -4840,7 +4858,7 @@ pub const Blob = struct { Blob.max_size; store.data.file.mode = @intCast(stat.mode); store.data.file.seekable = bun.isRegularFile(stat.mode); - store.data.file.last_modified = JSC.toJSTime(stat.mtime().tv_sec, stat.mtime().tv_nsec); + store.data.file.last_modified = JSC.toJSTime(stat.mtime().sec, stat.mtime().nsec); }, // the file may not exist yet. Thats's okay. else => {}, @@ -4875,7 +4893,7 @@ pub const Blob = struct { if (try options.get(globalThis, "type")) |content_type| { inner: { if (content_type.isString()) { - var content_type_str = content_type.toSlice(globalThis, bun.default_allocator); + var content_type_str = try content_type.toSlice(globalThis, bun.default_allocator); defer content_type_str.deinit(); const slice = content_type_str.slice(); if (!strings.isAllASCII(slice)) { @@ -5588,7 +5606,7 @@ pub const Blob = struct { JSC.JSValue.JSType.StringObject, JSC.JSValue.JSType.DerivedStringObject, => { - var sliced = current.toSlice(global, bun.default_allocator); + var sliced = try current.toSlice(global, bun.default_allocator); const allocator = sliced.allocator.get(); could_have_non_ascii = could_have_non_ascii or !sliced.allocator.isWTFAllocator(); joiner.push(sliced.slice(), allocator); @@ -5614,7 +5632,7 @@ pub const Blob = struct { .StringObject, .DerivedStringObject, => { - var sliced = item.toSlice(global, bun.default_allocator); + var sliced = try item.toSlice(global, bun.default_allocator); const allocator = sliced.allocator.get(); could_have_non_ascii = could_have_non_ascii or !sliced.allocator.isWTFAllocator(); joiner.push(sliced.slice(), allocator); @@ -5697,7 +5715,7 @@ pub const Blob = struct { }, else => { - var sliced = current.toSlice(global, bun.default_allocator); + var sliced = try current.toSlice(global, bun.default_allocator); if (global.hasException()) { const end_result = try joiner.done(bun.default_allocator); bun.default_allocator.free(end_result); diff --git a/src/bun.js/webcore/blob/ReadFile.zig b/src/bun.js/webcore/blob/ReadFile.zig index 2add4b0053e365..040ff469b4f6e9 100644 --- a/src/bun.js/webcore/blob/ReadFile.zig +++ b/src/bun.js/webcore/blob/ReadFile.zig @@ -1,14 +1,14 @@ const bun = @import("root").bun; const JSC = bun.JSC; const std = @import("std"); -const Blob = JSC.WebCore.Blob; +const Blob = bun.JSC.WebCore.Blob; const invalid_fd = bun.invalid_fd; const SystemError = JSC.SystemError; const SizeType = Blob.SizeType; const io = bun.io; -const FileOpenerMixin = Blob.Store.FileOpenerMixin; -const FileCloserMixin = Blob.Store.FileCloserMixin; +const FileOpenerMixin = Store.FileOpenerMixin; +const FileCloserMixin = Store.FileCloserMixin; const Environment = bun.Environment; const bloblog = bun.Output.scoped(.WriteFile, true); const JSPromise = JSC.JSPromise; @@ -24,7 +24,7 @@ pub fn NewReadFileHandler(comptime Function: anytype) type { promise: JSPromise.Strong = .{}, globalThis: *JSGlobalObject, - pub fn run(handler: *@This(), maybe_bytes: Blob.ReadFile.ResultType) void { + pub fn run(handler: *@This(), maybe_bytes: ReadFileResultType) void { var promise = handler.promise.swap(); var blob = handler.context; blob.allocator = null; @@ -34,7 +34,7 @@ pub fn NewReadFileHandler(comptime Function: anytype) type { .result => |result| { const bytes = result.buf; if (blob.size > 0) - blob.size = @min(@as(Blob.SizeType, @truncate(bytes.len)), blob.size); + blob.size = @min(@as(SizeType, @truncate(bytes.len)), blob.size); const WrappedFn = struct { pub fn wrapped(b: *Blob, g: *JSGlobalObject, by: []u8) JSC.JSValue { return JSC.toJSHostValue(g, Function(b, g, by, .temporary)); @@ -56,6 +56,11 @@ const ByteStore = Blob.ByteStore; const Store = Blob.Store; const ClosingState = Blob.ClosingState; +pub const ReadFileOnReadFileCallback = *const fn (ctx: *anyopaque, bytes: ReadFileResultType) void; +pub const ReadFileRead = struct { buf: []u8, is_temporary: bool = false, total_size: SizeType = 0 }; +pub const ReadFileResultType = SystemError.Maybe(ReadFileRead); +pub const ReadFileTask = JSC.WorkTask(ReadFile); + pub const ReadFile = struct { file_store: FileStore, byte_store: ByteStore = ByteStore{ .allocator = bun.default_allocator }, @@ -72,7 +77,7 @@ pub const ReadFile = struct { system_error: ?JSC.SystemError = null, errno: ?anyerror = null, onCompleteCtx: *anyopaque = undefined, - onCompleteCallback: OnReadFileCallback = undefined, + onCompleteCallback: ReadFileOnReadFileCallback = undefined, io_task: ?*ReadFileTask = null, io_poll: bun.io.Poll = .{}, io_request: bun.io.Request = .{ .callback = &onRequestReadable }, @@ -80,19 +85,11 @@ pub const ReadFile = struct { close_after_io: bool = false, state: std.atomic.Value(ClosingState) = std.atomic.Value(ClosingState).init(.running), - pub const Read = struct { - buf: []u8, - is_temporary: bool = false, - total_size: SizeType = 0, - }; - pub const ResultType = SystemError.Maybe(Read); - - pub const OnReadFileCallback = *const fn (ctx: *anyopaque, bytes: ResultType) void; - pub usingnamespace FileOpenerMixin(ReadFile); pub usingnamespace FileCloserMixin(ReadFile); pub fn update(this: *ReadFile) void { + if (Environment.isWindows) return; //why switch (this.state.load(.monotonic)) { .closing => { this.onFinish(); @@ -105,7 +102,7 @@ pub const ReadFile = struct { _: std.mem.Allocator, store: *Store, onReadFileContext: *anyopaque, - onCompleteCallback: OnReadFileCallback, + onCompleteCallback: ReadFileOnReadFileCallback, off: SizeType, max_len: SizeType, ) !*ReadFile { @@ -131,13 +128,13 @@ pub const ReadFile = struct { max_len: SizeType, comptime Context: type, context: Context, - comptime callback: fn (ctx: Context, bytes: ResultType) void, + comptime callback: fn (ctx: Context, bytes: ReadFileResultType) void, ) !*ReadFile { if (Environment.isWindows) @compileError("dont call this function on windows"); const Handler = struct { - pub fn run(ptr: *anyopaque, bytes: ResultType) void { + pub fn run(ptr: *anyopaque, bytes: ReadFileResultType) void { callback(bun.cast(Context, ptr), bytes); } }; @@ -257,8 +254,6 @@ pub const ReadFile = struct { return true; } - pub const ReadFileTask = JSC.WorkTask(@This()); - pub fn then(this: *ReadFile, _: *JSC.JSGlobalObject) void { const cb = this.onCompleteCallback; const cb_ctx = this.onCompleteCtx; @@ -266,12 +261,12 @@ pub const ReadFile = struct { if (this.store == null and this.system_error != null) { const system_error = this.system_error.?; bun.destroy(this); - cb(cb_ctx, ResultType{ .err = system_error }); + cb(cb_ctx, ReadFileResultType{ .err = system_error }); return; } else if (this.store == null) { bun.destroy(this); if (Environment.allow_assert) @panic("assertion failure - store should not be null"); - cb(cb_ctx, ResultType{ + cb(cb_ctx, ReadFileResultType{ .err = SystemError{ .code = bun.String.static("INTERNAL_ERROR"), .message = bun.String.static("assertion failure - store should not be null"), @@ -290,7 +285,7 @@ pub const ReadFile = struct { bun.destroy(this); if (system_error) |err| { - cb(cb_ctx, ResultType{ .err = err }); + cb(cb_ctx, ReadFileResultType{ .err = err }); return; } @@ -302,6 +297,7 @@ pub const ReadFile = struct { } fn runAsync(this: *ReadFile, task: *ReadFileTask) void { + if (Environment.isWindows) return; //why this.io_task = task; if (this.file_store.pathlike == .fd) { @@ -347,7 +343,7 @@ pub const ReadFile = struct { if (this.store) |store| { if (store.data == .file) { - store.data.file.last_modified = JSC.toJSTime(stat.mtime().tv_sec, stat.mtime().tv_nsec); + store.data.file.last_modified = JSC.toJSTime(stat.mtime().sec, stat.mtime().nsec); } } @@ -445,6 +441,7 @@ pub const ReadFile = struct { } fn doReadLoop(this: *ReadFile) void { + if (Environment.isWindows) return; //why while (this.state.load(.monotonic) == .running) { // we hold a 64 KB stack buffer incase the amount of data to // be read is greater than the reported amount @@ -563,7 +560,7 @@ pub const ReadFileUV = struct { system_error: ?JSC.SystemError = null, errno: ?anyerror = null, on_complete_data: *anyopaque = undefined, - on_complete_fn: ReadFile.OnReadFileCallback, + on_complete_fn: ReadFileOnReadFileCallback, is_regular_file: bool = false, req: libuv.fs_t = std.mem.zeroes(libuv.fs_t), @@ -596,7 +593,7 @@ pub const ReadFileUV = struct { const cb_ctx = this.on_complete_data; if (this.system_error) |err| { - cb(cb_ctx, ReadFile.ResultType{ .err = err }); + cb(cb_ctx, ReadFileResultType{ .err = err }); return; } @@ -661,7 +658,7 @@ pub const ReadFileUV = struct { // keep in sync with resolveSizeAndLastModified if (this.store.data == .file) { - this.store.data.file.last_modified = JSC.toJSTime(stat.mtime().tv_sec, stat.mtime().tv_nsec); + this.store.data.file.last_modified = JSC.toJSTime(stat.mtime().sec, stat.mtime().nsec); } if (bun.S.ISDIR(@intCast(stat.mode))) { diff --git a/src/bun.js/webcore/blob/WriteFile.zig b/src/bun.js/webcore/blob/WriteFile.zig index 9560fc4cd2f18f..06416629c53f05 100644 --- a/src/bun.js/webcore/blob/WriteFile.zig +++ b/src/bun.js/webcore/blob/WriteFile.zig @@ -17,6 +17,10 @@ const ZigString = JSC.ZigString; const ClosingState = Blob.ClosingState; +pub const WriteFileResultType = SystemError.Maybe(SizeType); +pub const WriteFileOnWriteFileCallback = *const fn (ctx: *anyopaque, count: WriteFileResultType) void; +pub const WriteFileTask = JSC.WorkTask(WriteFile); + pub const WriteFile = struct { file_blob: Blob, bytes_blob: Blob, @@ -31,15 +35,13 @@ pub const WriteFile = struct { state: std.atomic.Value(ClosingState) = std.atomic.Value(ClosingState).init(.running), onCompleteCtx: *anyopaque = undefined, - onCompleteCallback: OnWriteFileCallback = undefined, + onCompleteCallback: WriteFileOnWriteFileCallback = undefined, total_written: usize = 0, could_block: bool = false, close_after_io: bool = false, mkdirp_if_not_exists: bool = false, - pub const ResultType = SystemError.Maybe(SizeType); - pub const OnWriteFileCallback = *const fn (ctx: *anyopaque, count: ResultType) void; pub const io_tag = io.Poll.Tag.WriteFile; pub usingnamespace FileOpenerMixin(WriteFile); @@ -92,7 +94,7 @@ pub const WriteFile = struct { file_blob: Blob, bytes_blob: Blob, onWriteFileContext: *anyopaque, - onCompleteCallback: OnWriteFileCallback, + onCompleteCallback: WriteFileOnWriteFileCallback, mkdirp_if_not_exists: bool, ) !*WriteFile { const write_file = bun.new(WriteFile, WriteFile{ @@ -113,11 +115,11 @@ pub const WriteFile = struct { bytes_blob: Blob, comptime Context: type, context: Context, - comptime callback: fn (ctx: Context, bytes: ResultType) void, + comptime callback: fn (ctx: Context, bytes: WriteFileResultType) void, mkdirp_if_not_exists: bool, ) !*WriteFile { const Handler = struct { - pub fn run(ptr: *anyopaque, bytes: ResultType) void { + pub fn run(ptr: *anyopaque, bytes: WriteFileResultType) void { callback(bun.cast(Context, ptr), bytes); } }; @@ -178,8 +180,6 @@ pub const WriteFile = struct { return true; } - pub const WriteFileTask = JSC.WorkTask(@This()); - pub fn then(this: *WriteFile, _: *JSC.JSGlobalObject) void { const cb = this.onCompleteCallback; const cb_ctx = this.onCompleteCtx; @@ -199,6 +199,7 @@ pub const WriteFile = struct { bun.destroy(this); cb(cb_ctx, .{ .result = @as(SizeType, @truncate(wrote)) }); } + pub fn run(this: *WriteFile, task: *WriteFileTask) void { if (Environment.isWindows) { @panic("todo"); @@ -308,6 +309,7 @@ pub const WriteFile = struct { } fn doWriteLoop(this: *WriteFile) void { + if (Environment.isWindows) return; //why while (this.state.load(.monotonic) == .running) { var remain = this.bytes_blob.sharedView(); @@ -355,7 +357,7 @@ pub const WriteFileWindows = struct { io_request: uv.fs_t, file_blob: Blob, bytes_blob: Blob, - onCompleteCallback: OnWriteFileCallback, + onCompleteCallback: WriteFileOnWriteFileCallback, onCompleteCtx: *anyopaque, mkdirp_if_not_exists: bool = false, uv_bufs: [1]uv.uv_buf_t, @@ -374,7 +376,7 @@ pub const WriteFileWindows = struct { bytes_blob: Blob, event_loop: *bun.JSC.EventLoop, onWriteFileContext: *anyopaque, - onCompleteCallback: OnWriteFileCallback, + onCompleteCallback: WriteFileOnWriteFileCallback, mkdirp_if_not_exists: bool, ) *WriteFileWindows { const write_file = WriteFileWindows.new(.{ @@ -419,8 +421,6 @@ pub const WriteFileWindows = struct { write_file.event_loop.refConcurrently(); return write_file; } - pub const ResultType = WriteFile.ResultType; - pub const OnWriteFileCallback = WriteFile.OnWriteFileCallback; pub inline fn loop(this: *const WriteFileWindows) *uv.Loop { return this.event_loop.virtual_machine.event_loop_handle.?; @@ -637,7 +637,7 @@ pub const WriteFileWindows = struct { bytes_blob: Blob, comptime Context: type, context: Context, - comptime callback: *const fn (ctx: Context, bytes: ResultType) void, + comptime callback: *const fn (ctx: Context, bytes: WriteFileResultType) void, mkdirp_if_not_exists: bool, ) *WriteFileWindows { return WriteFileWindows.createWithCtx( @@ -654,7 +654,7 @@ pub const WriteFileWindows = struct { pub const WriteFilePromise = struct { promise: JSPromise.Strong = .{}, globalThis: *JSGlobalObject, - pub fn run(handler: *@This(), count: Blob.WriteFile.ResultType) void { + pub fn run(handler: *@This(), count: WriteFileResultType) void { var promise = handler.promise.swap(); const globalThis = handler.globalThis; bun.destroy(handler); diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig index abdfa55d877984..3452ec5e662d55 100644 --- a/src/bun.js/webcore/body.zig +++ b/src/bun.js/webcore/body.zig @@ -578,7 +578,7 @@ pub const Body = struct { }; } - if (js_type.isTypedArray()) { + if (js_type.isTypedArrayOrArrayBuffer()) { if (value.asArrayBuffer(globalThis)) |buffer| { const bytes = buffer.byteSlice(); @@ -1427,7 +1427,7 @@ pub const BodyValueBufferer = struct { global: *JSGlobalObject, allocator: std.mem.Allocator, ) @This() { - const this = .{ + const this: BodyValueBufferer = .{ .ctx = ctx, .onFinishedBuffering = onFinish, .allocator = allocator, @@ -1486,7 +1486,7 @@ pub const BodyValueBufferer = struct { } } - fn onFinishedLoadingFile(sink: *@This(), bytes: JSC.WebCore.Blob.ReadFile.ResultType) void { + fn onFinishedLoadingFile(sink: *@This(), bytes: Blob.ReadFileResultType) void { switch (bytes) { .err => |err| { log("onFinishedLoadingFile Error", .{}); @@ -1721,12 +1721,10 @@ pub const BodyValueBufferer = struct { }); comptime { - if (!JSC.is_bindgen) { - const jsonResolveStream = JSC.toJSHostFunction(onResolveStream); - @export(jsonResolveStream, .{ .name = Export[0].symbol_name }); - const jsonRejectStream = JSC.toJSHostFunction(onRejectStream); - @export(jsonRejectStream, .{ .name = Export[1].symbol_name }); - } + const jsonResolveStream = JSC.toJSHostFunction(onResolveStream); + @export(&jsonResolveStream, .{ .name = Export[0].symbol_name }); + const jsonRejectStream = JSC.toJSHostFunction(onRejectStream); + @export(&jsonRejectStream, .{ .name = Export[1].symbol_name }); } }; diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig index ed76e0e238c71b..0c58eb0390561f 100644 --- a/src/bun.js/webcore/encoding.zig +++ b/src/bun.js/webcore/encoding.zig @@ -31,7 +31,7 @@ const JSValue = JSC.JSValue; const JSGlobalObject = JSC.JSGlobalObject; const VirtualMachine = JSC.VirtualMachine; -const Task = @import("../javascript.zig").Task; +const Task = JSC.Task; const picohttp = bun.picohttp; @@ -239,13 +239,11 @@ pub const TextEncoder = struct { }; comptime { - if (!JSC.is_bindgen) { - _ = TextEncoder.TextEncoder__encode8; - _ = TextEncoder.TextEncoder__encode16; - _ = TextEncoder.TextEncoder__encodeInto8; - _ = TextEncoder.TextEncoder__encodeInto16; - _ = TextEncoder.TextEncoder__encodeRopeString; - } + _ = TextEncoder.TextEncoder__encode8; + _ = TextEncoder.TextEncoder__encode16; + _ = TextEncoder.TextEncoder__encodeInto8; + _ = TextEncoder.TextEncoder__encodeInto16; + _ = TextEncoder.TextEncoder__encodeRopeString; } /// https://encoding.spec.whatwg.org/encodings.json @@ -892,7 +890,7 @@ pub const TextDecoder = struct { if (arguments.len > 0) { // encoding if (arguments[0].isString()) { - var str = arguments[0].toSlice(globalThis, bun.default_allocator); + var str = try arguments[0].toSlice(globalThis, bun.default_allocator); defer if (str.isAllocated()) str.deinit(); if (EncodingLabel.which(str.slice())) |label| { @@ -1128,7 +1126,6 @@ pub const Encoder = struct { pub fn toStringComptime(input: []const u8, global: *JSGlobalObject, comptime encoding: JSC.Node.Encoding) JSValue { var bun_string = toBunStringComptime(input, encoding); - defer bun_string.deref(); return bun_string.transferToJS(global); } @@ -1154,7 +1151,14 @@ pub const Encoder = struct { return str; }, .buffer, .utf8 => { - return bun.String.createUTF8(input); + const converted = strings.toUTF16Alloc(bun.default_allocator, input, false, false) catch return bun.String.dead; + if (converted) |utf16| { + return bun.String.createExternalGloballyAllocated(.utf16, utf16); + } + + // If we get here, it means we can safely assume the string is 100% ASCII characters + // For this, we rely on WebKit to manage the memory. + return bun.String.createLatin1(input); }, .ucs2, .utf16le => { // Avoid incomplete characters @@ -1177,16 +1181,17 @@ pub const Encoder = struct { }, .base64url => { - const str, const chars = bun.String.createUninitialized(.latin1, bun.base64.urlSafeEncodeLen(input)); - _ = bun.base64.encodeURLSafe(chars, input); - return str; + const to_len = bun.base64.urlSafeEncodeLen(input); + const to = bun.default_allocator.alloc(u8, to_len) catch return bun.String.dead; + const wrote = bun.base64.encodeURLSafe(to, input); + return bun.String.createExternalGloballyAllocated(.latin1, to[0..wrote]); }, .base64 => { const to_len = bun.base64.encodeLen(input); - const str, const chars = bun.String.createUninitialized(.latin1, to_len); - _ = bun.base64.encode(chars, input); - return str; + const to = bun.default_allocator.alloc(u8, to_len) catch return bun.String.dead; + const wrote = bun.base64.encode(to, input); + return bun.String.createExternalGloballyAllocated(.latin1, to[0..wrote]); }, } } @@ -1464,24 +1469,20 @@ pub const Encoder = struct { } comptime { - if (!JSC.is_bindgen) { - _ = Bun__encoding__writeLatin1; - _ = Bun__encoding__writeUTF16; + _ = Bun__encoding__writeLatin1; + _ = Bun__encoding__writeUTF16; - _ = Bun__encoding__byteLengthLatin1; - _ = Bun__encoding__byteLengthUTF16; + _ = Bun__encoding__byteLengthLatin1; + _ = Bun__encoding__byteLengthUTF16; - _ = Bun__encoding__toString; - _ = Bun__encoding__toStringUTF8; + _ = Bun__encoding__toString; + _ = Bun__encoding__toStringUTF8; - _ = Bun__encoding__constructFromLatin1; - _ = Bun__encoding__constructFromUTF16; - } + _ = Bun__encoding__constructFromLatin1; + _ = Bun__encoding__constructFromUTF16; } }; comptime { - if (!JSC.is_bindgen) { - std.testing.refAllDecls(Encoder); - } + std.testing.refAllDecls(Encoder); } diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig index 7274373be0bfb1..4d85d4226c33c0 100644 --- a/src/bun.js/webcore/request.zig +++ b/src/bun.js/webcore/request.zig @@ -107,11 +107,9 @@ pub const Request = struct { } comptime { - if (!JSC.is_bindgen) { - _ = Request__getUWSRequest; - _ = Request__setInternalEventCallback; - _ = Request__setTimeout; - } + _ = Request__getUWSRequest; + _ = Request__setInternalEventCallback; + _ = Request__setTimeout; } pub const InternalJSEventCallback = struct { @@ -490,6 +488,7 @@ pub const Request = struct { const href = bun.JSC.URL.hrefFromString(this.url); // TODO: what is the right thing to do for invalid URLS? if (!href.isEmpty()) { + this.url.deref(); this.url = href; } @@ -612,7 +611,7 @@ pub const Request = struct { } } - if (value.asDirect(JSC.WebCore.Response)) |response| { + if (value.asDirect(Response)) |response| { if (!fields.contains(.method)) { req.method = response.init.method; fields.insert(.method); diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index 8ad9bb4d8ea277..a5bf52f203b5b7 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -898,7 +898,7 @@ pub const Fetch = struct { pub const Empty: HTTPRequestBody = .{ .AnyBlob = .{ .Blob = .{} } }; - pub fn store(this: *HTTPRequestBody) ?*JSC.WebCore.Blob.Store { + pub fn store(this: *HTTPRequestBody) ?*Blob.Store { return switch (this.*) { .AnyBlob => this.AnyBlob.store(), else => null, @@ -1127,9 +1127,9 @@ pub const Fetch = struct { }); comptime { const jsonResolveRequestStream = JSC.toJSHostFunction(onResolveRequestStream); - @export(jsonResolveRequestStream, .{ .name = Export[0].symbol_name }); + @export(&jsonResolveRequestStream, .{ .name = Export[0].symbol_name }); const jsonRejectRequestStream = JSC.toJSHostFunction(onRejectRequestStream); - @export(jsonRejectRequestStream, .{ .name = Export[1].symbol_name }); + @export(&jsonRejectRequestStream, .{ .name = Export[1].symbol_name }); } pub fn startRequestStream(this: *FetchTasklet) void { @@ -1947,6 +1947,7 @@ pub const Fetch = struct { fetch_tasklet.signals.cert_errors = null; } + // This task gets queued on the HTTP thread. fetch_tasklet.http.?.* = http.AsyncHTTP.init( fetch_options.memory_reporter.allocator(), fetch_options.method, @@ -1957,6 +1958,7 @@ pub const Fetch = struct { fetch_tasklet.request_body.slice(), http.HTTPClientResult.Callback.New( *FetchTasklet, + // handles response events (on headers, on body, etc.) FetchTasklet.callback, ).init(fetch_tasklet), fetch_options.redirect_type, @@ -2083,6 +2085,7 @@ pub const Fetch = struct { return node; } + /// Called from HTTP thread. Handles HTTP events received from socket. pub fn callback(task: *FetchTasklet, async_http: *http.AsyncHTTP, result: http.HTTPClientResult) void { // at this point only this thread is accessing result to is no race condition const is_done = !result.has_more; @@ -2200,7 +2203,7 @@ pub const Fetch = struct { comptime { const Bun__fetchPreconnect = JSC.toJSHostFunction(Bun__fetchPreconnect_); - @export(Bun__fetchPreconnect, .{ .name = "Bun__fetchPreconnect" }); + @export(&Bun__fetchPreconnect, .{ .name = "Bun__fetchPreconnect" }); } pub fn Bun__fetchPreconnect_( globalObject: *JSC.JSGlobalObject, @@ -2261,8 +2264,10 @@ pub const Fetch = struct { comptime { const Bun__fetch = JSC.toJSHostFunction(Bun__fetch_); - @export(Bun__fetch, .{ .name = "Bun__fetch" }); + @export(&Bun__fetch, .{ .name = "Bun__fetch" }); } + + /// Implementation of `Bun.fetch` pub fn Bun__fetch_( ctx: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 398ed5b8ba84a6..5fc56a1c327bc3 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -5,7 +5,6 @@ const MimeType = HTTPClient.MimeType; const ZigURL = @import("../../url.zig").URL; const HTTPClient = bun.http; const JSC = bun.JSC; -const js = JSC.C; const Method = @import("../../http/method.zig").Method; const FetchHeaders = JSC.FetchHeaders; @@ -37,14 +36,14 @@ const JSPrinter = bun.js_printer; const picohttp = bun.picohttp; const StringJoiner = bun.StringJoiner; const uws = bun.uws; -const Blob = JSC.WebCore.Blob; +const Blob = bun.JSC.WebCore.Blob; const Response = JSC.WebCore.Response; const Request = JSC.WebCore.Request; const assert = bun.assert; const Syscall = bun.sys; const uv = bun.windows.libuv; -const AnyBlob = JSC.WebCore.AnyBlob; +const AnyBlob = bun.JSC.WebCore.AnyBlob; pub const ReadableStream = struct { value: JSValue, ptr: Source, @@ -124,7 +123,7 @@ pub const ReadableStream = struct { pub fn toAnyBlob( stream: *ReadableStream, globalThis: *JSC.JSGlobalObject, - ) ?JSC.WebCore.AnyBlob { + ) ?AnyBlob { if (stream.isDisturbed(globalThis)) { return null; } @@ -140,7 +139,7 @@ pub const ReadableStream = struct { }, .File => |blobby| { if (blobby.lazy == .blob) { - var blob = JSC.WebCore.Blob.initWithStore(blobby.lazy.blob, globalThis); + var blob = Blob.initWithStore(blobby.lazy.blob, globalThis); blob.store.?.ref(); // it should be lazy, file shouldn't have opened yet. bun.assert(!blobby.started); @@ -493,7 +492,7 @@ pub const StreamStart = union(Tag) { close: bool = false, mode: bun.Mode = 0o664, - pub fn flags(this: *const FileSinkOptions) bun.Mode { + pub fn flags(this: *const FileSinkOptions) i32 { _ = this; return bun.O.NONBLOCK | bun.O.CLOEXEC | bun.O.CREAT | bun.O.WRONLY; @@ -563,7 +562,7 @@ pub const StreamStart = union(Tag) { .ArrayBufferSink => { var as_uint8array = false; var stream = false; - var chunk_size: JSC.WebCore.Blob.SizeType = 0; + var chunk_size: Blob.SizeType = 0; var empty = true; if (value.getOwn(globalThis, "asUint8Array")) |val| { @@ -583,7 +582,7 @@ pub const StreamStart = union(Tag) { if (value.fastGet(globalThis, .highWaterMark)) |chunkSize| { if (chunkSize.isNumber()) { empty = false; - chunk_size = @as(JSC.WebCore.Blob.SizeType, @intCast(@max(0, @as(i51, @truncate(chunkSize.toInt64()))))); + chunk_size = @as(Blob.SizeType, @intCast(@max(0, @as(i51, @truncate(chunkSize.toInt64()))))); } } @@ -598,11 +597,11 @@ pub const StreamStart = union(Tag) { } }, .FileSink => { - var chunk_size: JSC.WebCore.Blob.SizeType = 0; + var chunk_size: Blob.SizeType = 0; if (value.fastGet(globalThis, .highWaterMark)) |chunkSize| { if (chunkSize.isNumber()) - chunk_size = @as(JSC.WebCore.Blob.SizeType, @intCast(@max(0, @as(i51, @truncate(chunkSize.toInt64()))))); + chunk_size = @as(Blob.SizeType, @intCast(@max(0, @as(i51, @truncate(chunkSize.toInt64()))))); } if (value.fastGet(globalThis, .path)) |path| { @@ -619,7 +618,7 @@ pub const StreamStart = union(Tag) { .FileSink = .{ .chunk_size = chunk_size, .input_path = .{ - .path = path.toSlice(globalThis, globalThis.bunVM().allocator), + .path = try path.toSlice(globalThis, globalThis.bunVM().allocator), }, }, }; @@ -661,12 +660,12 @@ pub const StreamStart = union(Tag) { }, .NetworkSink, .HTTPSResponseSink, .HTTPResponseSink => { var empty = true; - var chunk_size: JSC.WebCore.Blob.SizeType = 2048; + var chunk_size: Blob.SizeType = 2048; if (value.fastGet(globalThis, .highWaterMark)) |chunkSize| { if (chunkSize.isNumber()) { empty = false; - chunk_size = @as(JSC.WebCore.Blob.SizeType, @intCast(@max(256, @as(i51, @truncate(chunkSize.toInt64()))))); + chunk_size = @as(Blob.SizeType, @intCast(@max(256, @as(i51, @truncate(chunkSize.toInt64()))))); } } @@ -1563,7 +1562,7 @@ pub const ArrayBufferSink = struct { pub const JSSink = NewJSSink(@This(), "ArrayBufferSink"); }; -const AutoFlusher = struct { +pub const AutoFlusher = struct { registered: bool = false, pub fn registerDeferredMicrotaskWithType(comptime Type: type, this: *Type, vm: *JSC.VirtualMachine) void { @@ -1609,10 +1608,10 @@ pub const SinkDestructor = struct { } switch (ptr.tag()) { - .Detached => { + @field(Ptr.Tag, @typeName(Detached)) => { return; }, - .Subprocess => { + @field(Ptr.Tag, @typeName(Subprocess)) => { const subprocess = ptr.as(Subprocess); subprocess.onStdinDestroyed(); }, @@ -1983,17 +1982,17 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { } comptime { - @export(finalize, .{ .name = shim.symbolName("finalize") }); - @export(jsWrite, .{ .name = shim.symbolName("write") }); - @export(jsGetInternalFd, .{ .name = shim.symbolName("getInternalFd") }); - @export(close, .{ .name = shim.symbolName("close") }); - @export(jsFlush, .{ .name = shim.symbolName("flush") }); - @export(jsStart, .{ .name = shim.symbolName("start") }); - @export(jsEnd, .{ .name = shim.symbolName("end") }); - @export(jsConstruct, .{ .name = shim.symbolName("construct") }); - @export(endWithSink, .{ .name = shim.symbolName("endWithSink") }); - @export(updateRef, .{ .name = shim.symbolName("updateRef") }); - @export(memoryCost, .{ .name = shim.symbolName("memoryCost") }); + @export(&finalize, .{ .name = shim.symbolName("finalize") }); + @export(&jsWrite, .{ .name = shim.symbolName("write") }); + @export(&jsGetInternalFd, .{ .name = shim.symbolName("getInternalFd") }); + @export(&close, .{ .name = shim.symbolName("close") }); + @export(&jsFlush, .{ .name = shim.symbolName("flush") }); + @export(&jsStart, .{ .name = shim.symbolName("start") }); + @export(&jsEnd, .{ .name = shim.symbolName("end") }); + @export(&jsConstruct, .{ .name = shim.symbolName("construct") }); + @export(&endWithSink, .{ .name = shim.symbolName("endWithSink") }); + @export(&updateRef, .{ .name = shim.symbolName("updateRef") }); + @export(&memoryCost, .{ .name = shim.symbolName("memoryCost") }); shim.assertJSFunction(.{ write, @@ -2894,7 +2893,8 @@ pub const NetworkSink = struct { return .{ .owned = len }; } - this.buffer.writeLatin1(bytes) catch { + const check_ascii = false; + this.buffer.writeLatin1(bytes, check_ascii) catch { return .{ .err = Syscall.Error.fromCode(.NOMEM, .write) }; }; @@ -2905,7 +2905,9 @@ pub const NetworkSink = struct { } else if (this.buffer.size() + len >= this.getHighWaterMark()) { // kinda fast path: // - combined chunk is large enough to flush automatically - this.buffer.writeLatin1(bytes) catch { + + const check_ascii = true; + this.buffer.writeLatin1(bytes, check_ascii) catch { return .{ .err = Syscall.Error.fromCode(.NOMEM, .write) }; }; _ = this.internalFlush() catch { @@ -2913,7 +2915,8 @@ pub const NetworkSink = struct { }; return .{ .owned = len }; } else { - this.buffer.writeLatin1(bytes) catch { + const check_ascii = true; + this.buffer.writeLatin1(bytes, check_ascii) catch { return .{ .err = Syscall.Error.fromCode(.NOMEM, .write) }; }; } @@ -3421,14 +3424,17 @@ pub const FileSink = struct { // we should not duplicate these fields... pollable: bool = false, nonblocking: bool = false, - force_sync_on_windows: bool = false, + force_sync: bool = false, + is_socket: bool = false, fd: bun.FileDescriptor = bun.invalid_fd, - has_js_called_unref: bool = false, + + auto_flusher: AutoFlusher = .{}, + run_pending_later: FlushPendingFileSinkTask = .{}, const log = Output.scoped(.FileSink, false); - pub usingnamespace bun.NewRefCounted(FileSink, deinit); + pub usingnamespace bun.NewRefCounted(FileSink, deinit, null); pub const IOWriter = bun.io.StreamingWriter(@This(), onWrite, onError, onReady, onClose); pub const Poll = IOWriter; @@ -3438,17 +3444,19 @@ pub const FileSink = struct { return this.writer.memoryCost(); } - fn Bun__ForceFileSinkToBeSynchronousOnWindows(globalObject: *JSC.JSGlobalObject, jsvalue: JSC.JSValue) callconv(.C) void { - comptime bun.assert(Environment.isWindows); - + fn Bun__ForceFileSinkToBeSynchronousForProcessObjectStdio(globalObject: *JSC.JSGlobalObject, jsvalue: JSC.JSValue) callconv(.C) void { var this: *FileSink = @alignCast(@ptrCast(JSSink.fromJS(globalObject, jsvalue) orelse return)); - this.force_sync_on_windows = true; + this.force_sync = true; + if (comptime !Environment.isWindows) { + this.writer.force_sync = true; + if (this.fd != bun.invalid_fd) { + _ = bun.sys.updateNonblocking(this.fd, false); + } + } } comptime { - if (Environment.isWindows) { - @export(Bun__ForceFileSinkToBeSynchronousOnWindows, .{ .name = "Bun__ForceFileSinkToBeSynchronousOnWindows" }); - } + @export(&Bun__ForceFileSinkToBeSynchronousForProcessObjectStdio, .{ .name = "Bun__ForceFileSinkToBeSynchronousForProcessObjectStdio" }); } pub fn onAttachedProcessExit(this: *FileSink) void { @@ -3470,6 +3478,7 @@ pub const FileSink = struct { this.ref(); defer this.deref(); + this.run_pending_later.has = false; const l = this.eventLoop(); l.enter(); defer l.exit(); @@ -3488,6 +3497,14 @@ pub const FileSink = struct { // If there's no pending write, no need to keep the event loop ref'd. this.writer.updateRef(this.eventLoop(), has_pending_data); + if (has_pending_data) { + if (this.event_loop_handle.bunVM()) |vm| { + if (!vm.is_inside_deferred_task_queue) { + AutoFlusher.registerDeferredMicrotaskWithType(@This(), this, vm); + } + } + } + // if we are not done yet and has pending data we just wait so we do not runPending twice if (status == .pending and has_pending_data) { if (this.pending.state == .pending) { @@ -3532,6 +3549,12 @@ pub const FileSink = struct { log("onError({any})", .{err}); if (this.pending.state == .pending) { this.pending.result = .{ .err = err }; + if (this.eventLoop().bunVM()) |vm| { + if (vm.is_inside_deferred_task_queue) { + this.runPendingLater(); + return; + } + } this.runPending(); } @@ -3588,23 +3611,17 @@ pub const FileSink = struct { pub fn setup(this: *FileSink, options: *const StreamStart.FileSinkOptions) JSC.Maybe(void) { // TODO: this should be concurrent. - var isatty: ?bool = null; - var is_nonblocking_tty = false; + var isatty = false; + var is_nonblocking = false; const fd = switch (switch (options.input_path) { - .path => |path| bun.sys.openA(path.slice(), options.flags(), options.mode), + .path => |path| brk: { + is_nonblocking = true; + break :brk bun.sys.openA(path.slice(), options.flags(), options.mode); + }, .fd => |fd_| brk: { - if (comptime Environment.isPosix and FeatureFlags.nonblocking_stdout_and_stderr_on_posix) { - if (bun.FDTag.get(fd_) != .none) { - const rc = bun.C.open_as_nonblocking_tty(@intCast(fd_.cast()), bun.O.WRONLY); - if (rc > -1) { - isatty = true; - is_nonblocking_tty = true; - break :brk JSC.Maybe(bun.FileDescriptor){ .result = bun.toFD(rc) }; - } - } - } + const duped = bun.sys.dupWithFlags(fd_, 0); - break :brk bun.sys.dupWithFlags(fd_, if (bun.FDTag.get(fd_) == .none and !this.force_sync_on_windows) bun.O.NONBLOCK else 0); + break :brk duped; }, }) { .err => |err| return .{ .err = err }, @@ -3619,32 +3636,56 @@ pub const FileSink = struct { }, .result => |stat| { this.pollable = bun.sys.isPollable(stat.mode); - if (!this.pollable and isatty == null) { + if (!this.pollable) { isatty = std.posix.isatty(fd.int()); } - if (isatty) |is| { - if (is) - this.pollable = true; + if (isatty) { + this.pollable = true; } this.fd = fd; this.is_socket = std.posix.S.ISSOCK(stat.mode); - this.nonblocking = is_nonblocking_tty or (this.pollable and switch (options.input_path) { - .path => true, - .fd => |fd_| bun.FDTag.get(fd_) == .none, - }); + + if (this.force_sync or isatty) { + // Prevents interleaved or dropped stdout/stderr output for terminals. + // As noted in the following reference, local TTYs tend to be quite fast and + // this behavior has become expected due historical functionality on OS X, + // even though it was originally intended to change in v1.0.2 (Libuv 1.2.1). + // Ref: https://github.com/nodejs/node/pull/1771#issuecomment-119351671 + _ = bun.sys.updateNonblocking(fd, false); + is_nonblocking = false; + this.force_sync = true; + this.writer.force_sync = true; + } else if (!is_nonblocking) { + const flags = switch (bun.sys.getFcntlFlags(fd)) { + .result => |flags| flags, + .err => |err| { + _ = bun.sys.close(fd); + return .{ .err = err }; + }, + }; + is_nonblocking = (flags & @as(@TypeOf(flags), bun.O.NONBLOCK)) != 0; + + if (!is_nonblocking) { + if (bun.sys.setNonblocking(fd) == .result) { + is_nonblocking = true; + } + } + } + + this.nonblocking = is_nonblocking and this.pollable; }, } } else if (comptime Environment.isWindows) { - this.pollable = (bun.windows.GetFileType(fd.cast()) & bun.windows.FILE_TYPE_PIPE) != 0 and !this.force_sync_on_windows; + this.pollable = (bun.windows.GetFileType(fd.cast()) & bun.windows.FILE_TYPE_PIPE) != 0 and !this.force_sync; this.fd = fd; } else { @compileError("TODO: implement for this platform"); } if (comptime Environment.isWindows) { - if (this.force_sync_on_windows) { + if (this.force_sync) { switch (this.writer.startSync( fd, this.pollable, @@ -3721,6 +3762,51 @@ pub const FileSink = struct { return .{ .result = {} }; } + pub fn runPendingLater(this: *FileSink) void { + if (this.run_pending_later.has) { + return; + } + this.run_pending_later.has = true; + const event_loop = this.eventLoop(); + if (event_loop == .js) { + this.ref(); + event_loop.js.enqueueTask(JSC.Task.init(&this.run_pending_later)); + } + } + + pub fn onAutoFlush(this: *FileSink) bool { + if (this.done or !this.writer.hasPendingData()) { + this.updateRef(false); + this.auto_flusher.registered = false; + return false; + } + + this.ref(); + defer this.deref(); + + const amount_buffered = this.writer.outgoing.size(); + + switch (this.writer.flush()) { + .err, .done => { + this.updateRef(false); + this.runPendingLater(); + }, + .wrote => |amount_drained| { + if (amount_drained == amount_buffered) { + this.updateRef(false); + this.runPendingLater(); + } + }, + else => { + return true; + }, + } + + const is_registered = !this.writer.hasPendingData(); + this.auto_flusher.registered = is_registered; + return is_registered; + } + pub fn flush(_: *FileSink) JSC.Maybe(void) { return .{ .result = {} }; } @@ -3841,6 +3927,9 @@ pub const FileSink = struct { pub fn deinit(this: *FileSink) void { this.pending.deinit(); this.writer.deinit(); + if (this.event_loop_handle.globalObject()) |global| { + AutoFlusher.unregisterDeferredMicrotaskWithType(@This(), this, global.bunVM()); + } } pub fn toJS(this: *FileSink, globalThis: *JSGlobalObject) JSValue { @@ -3892,7 +3981,6 @@ pub const FileSink = struct { } pub fn updateRef(this: *FileSink, value: bool) void { - this.has_js_called_unref = !value; if (value) { this.writer.enableKeepingProcessAlive(this.event_loop_handle); } else { @@ -3943,6 +4031,18 @@ pub const FileSink = struct { } }; +pub const FlushPendingFileSinkTask = struct { + has: bool = false, + pub fn runFromJSThread(flush_pending: *FlushPendingFileSinkTask) void { + const had = flush_pending.has; + flush_pending.has = false; + const this: *FileSink = @alignCast(@fieldParentPtr("run_pending_later", flush_pending)); + defer this.deref(); + if (had) + this.runPending(); + } +}; + pub const FileReader = struct { const log = Output.scoped(.FileReader, false); reader: IOReader = IOReader.init(FileReader), @@ -3961,7 +4061,6 @@ pub const FileReader = struct { buffered: std.ArrayListUnmanaged(u8) = .{}, read_inside_on_pull: ReadDuringJSOnPullResult = .{ .none = {} }, highwater_mark: usize = 16384, - has_js_called_unref: bool = false, pub const IOReader = bun.io.BufferedReader; pub const Poll = IOReader; @@ -3989,37 +4088,43 @@ pub const FileReader = struct { pub fn openFileBlob(file: *Blob.FileStore) JSC.Maybe(OpenedFileBlob) { var this = OpenedFileBlob{ .fd = bun.invalid_fd }; var file_buf: bun.PathBuffer = undefined; - var is_nonblocking_tty = false; + var is_nonblocking = false; const fd = if (file.pathlike == .fd) if (file.pathlike.fd.isStdio()) brk: { if (comptime Environment.isPosix) { const rc = bun.C.open_as_nonblocking_tty(file.pathlike.fd.int(), bun.O.RDONLY); if (rc > -1) { - is_nonblocking_tty = true; + is_nonblocking = true; file.is_atty = true; break :brk bun.toFD(rc); } } break :brk file.pathlike.fd; - } else switch (Syscall.dupWithFlags(file.pathlike.fd, brk: { + } else brk: { + const duped = Syscall.dupWithFlags(file.pathlike.fd, 0); + + if (duped != .result) { + return .{ .err = duped.err.withFd(file.pathlike.fd) }; + } + + const fd = duped.result; + if (comptime Environment.isPosix) { - if (bun.FDTag.get(file.pathlike.fd) == .none and !(file.is_atty orelse false)) { - break :brk bun.O.NONBLOCK; + if (bun.FDTag.get(fd) == .none) { + is_nonblocking = switch (bun.sys.getFcntlFlags(fd)) { + .result => |flags| (flags & bun.O.NONBLOCK) != 0, + .err => false, + }; } } - break :brk 0; - })) { - .result => |fd| switch (bun.sys.toLibUVOwnedFD(fd, .dup, .close_on_fail)) { + break :brk switch (bun.sys.toLibUVOwnedFD(fd, .dup, .close_on_fail)) { .result => |owned_fd| owned_fd, .err => |err| { return .{ .err = err }; }, - }, - .err => |err| { - return .{ .err = err.withFd(file.pathlike.fd) }; - }, + }; } else switch (Syscall.open(file.pathlike.path.sliceZ(&file_buf), bun.O.RDONLY | bun.O.NONBLOCK | bun.O.CLOEXEC, 0)) { .result => |fd| fd, @@ -4055,7 +4160,7 @@ pub const FileReader = struct { return .{ .err = Syscall.Error.fromCode(.ISDIR, .fstat) }; } - this.pollable = bun.sys.isPollable(stat.mode) or is_nonblocking_tty or (file.is_atty orelse false); + this.pollable = bun.sys.isPollable(stat.mode) or is_nonblocking or (file.is_atty orelse false); this.file_type = if (bun.S.ISFIFO(stat.mode)) .pipe else if (bun.S.ISSOCK(stat.mode)) @@ -4064,11 +4169,11 @@ pub const FileReader = struct { .file; // pretend it's a non-blocking pipe if it's a TTY - if (is_nonblocking_tty and this.file_type != .socket) { + if (is_nonblocking and this.file_type != .socket) { this.file_type = .nonblocking_pipe; } - this.nonblocking = is_nonblocking_tty or (this.pollable and !(file.is_atty orelse false)); + this.nonblocking = is_nonblocking or (this.pollable and !(file.is_atty orelse false)); if (this.nonblocking and this.file_type == .pipe) { this.file_type = .nonblocking_pipe; @@ -4233,7 +4338,7 @@ pub const FileReader = struct { pub fn onReadChunk(this: *@This(), init_buf: []const u8, state: bun.io.ReadState) bool { var buf = init_buf; - log("onReadChunk() = {d} ({s})", .{ buf.len, @tagName(state) }); + log("onReadChunk() = {d} ({s}) - read_inside_on_pull: {s}", .{ buf.len, @tagName(state), @tagName(this.read_inside_on_pull) }); if (this.done) { this.reader.close(); @@ -4507,7 +4612,6 @@ pub const FileReader = struct { pub fn setRefOrUnref(this: *FileReader, enable: bool) void { if (this.done) return; - this.has_js_called_unref = !enable; this.reader.updateRef(enable); } @@ -4677,7 +4781,7 @@ pub const ByteBlobLoader = struct { } } - var blob = JSC.WebCore.Blob.initWithStore(store, globalThis); + var blob = Blob.initWithStore(store, globalThis); blob.offset = this.offset; blob.size = this.remain; this.parent().is_closed = true; diff --git a/src/bun.zig b/src/bun.zig index a61b2373dab8c7..e6a9b97dde0f1e 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -336,7 +336,7 @@ pub const OSPathSlice = []const OSPathChar; pub const OSPathBuffer = if (Environment.isWindows) WPathBuffer else PathBuffer; pub inline fn cast(comptime To: type, value: anytype) To { - if (@typeInfo(@TypeOf(value)) == .Int) { + if (@typeInfo(@TypeOf(value)) == .int) { return @ptrFromInt(@as(usize, value)); } @@ -345,12 +345,12 @@ pub inline fn cast(comptime To: type, value: anytype) To { pub fn len(value: anytype) usize { return switch (@typeInfo(@TypeOf(value))) { - .Array => |info| info.len, - .Vector => |info| info.len, - .Pointer => |info| switch (info.size) { - .One => switch (@typeInfo(info.child)) { - .Array => |array| brk: { - if (array.sentinel != null) { + .array => |info| info.len, + .vector => |info| info.len, + .pointer => |info| switch (info.size) { + .one => switch (@typeInfo(info.child)) { + .array => |array| brk: { + if (array.sentinel_ptr != null) { @compileError("use bun.sliceTo"); } @@ -358,20 +358,20 @@ pub fn len(value: anytype) usize { }, else => @compileError("invalid type given to std.mem.len"), }, - .Many => { - const sentinel_ptr = info.sentinel orelse + .many => { + const sentinel_ptr = info.sentinel_ptr orelse @compileError("length of pointer with no sentinel"); const sentinel = @as(*align(1) const info.child, @ptrCast(sentinel_ptr)).*; return std.mem.indexOfSentinel(info.child, sentinel, value); }, - .C => { + .c => { assert(value != null); return std.mem.indexOfSentinel(info.child, 0, value); }, - .Slice => value.len, + .slice => value.len, }, - .Struct => |info| if (info.is_tuple) { + .@"struct" => |info| if (info.is_tuple) { return info.fields.len; } else @compileError("invalid type given to std.mem.len"), else => @compileError("invalid type given to std.mem.len"), @@ -380,34 +380,34 @@ pub fn len(value: anytype) usize { fn Span(comptime T: type) type { switch (@typeInfo(T)) { - .Optional => |optional_info| { + .optional => |optional_info| { return ?Span(optional_info.child); }, - .Pointer => |ptr_info| { + .pointer => |ptr_info| { var new_ptr_info = ptr_info; switch (ptr_info.size) { - .One => switch (@typeInfo(ptr_info.child)) { - .Array => |info| { + .one => switch (@typeInfo(ptr_info.child)) { + .array => |info| { new_ptr_info.child = info.child; - new_ptr_info.sentinel = info.sentinel; + new_ptr_info.sentinel_ptr = info.sentinel_ptr; }, else => @compileError("invalid type given to std.mem.Span"), }, - .C => { - new_ptr_info.sentinel = &@as(ptr_info.child, 0); + .c => { + new_ptr_info.sentinel_ptr = &@as(ptr_info.child, 0); new_ptr_info.is_allowzero = false; }, - .Many, .Slice => {}, + .many, .slice => {}, } - new_ptr_info.size = .Slice; - return @Type(.{ .Pointer = new_ptr_info }); + new_ptr_info.size = .slice; + return @Type(.{ .pointer = new_ptr_info }); }, else => @compileError("invalid type given to std.mem.Span: " ++ @typeName(T)), } } pub fn span(ptr: anytype) Span(@TypeOf(ptr)) { - if (@typeInfo(@TypeOf(ptr)) == .Optional) { + if (@typeInfo(@TypeOf(ptr)) == .optional) { if (ptr) |non_null| { return span(non_null); } else { @@ -416,8 +416,8 @@ pub fn span(ptr: anytype) Span(@TypeOf(ptr)) { } const Result = Span(@TypeOf(ptr)); const l = len(ptr); - const ptr_info = @typeInfo(Result).Pointer; - if (ptr_info.sentinel) |s_ptr| { + const ptr_info = @typeInfo(Result).pointer; + if (ptr_info.sentinel_ptr) |s_ptr| { const s = @as(*align(1) const ptr_info.child, @ptrCast(s_ptr)).*; return ptr[0..l :s]; } else { @@ -591,11 +591,11 @@ pub fn fastRandom() u64 { } }; - var prng_: ?std.rand.DefaultPrng = null; + var prng_: ?std.Random.DefaultPrng = null; pub fn get() u64 { if (prng_ == null) { - prng_ = std.rand.DefaultPrng.init(random_seed.get()); + prng_ = std.Random.DefaultPrng.init(random_seed.get()); } return prng_.?.random().uintAtMost(u64, std.math.maxInt(u64)); @@ -808,7 +808,7 @@ pub const zlib = @import("./zlib.zig"); pub var start_time: i128 = 0; pub fn openFileZ(pathZ: [:0]const u8, open_flags: std.fs.File.OpenFlags) !std.fs.File { - var flags: Mode = 0; + var flags: i32 = 0; switch (open_flags.mode) { .read_only => flags |= O.RDONLY, .write_only => flags |= O.WRONLY, @@ -821,7 +821,7 @@ pub fn openFileZ(pathZ: [:0]const u8, open_flags: std.fs.File.OpenFlags) !std.fs pub fn openFile(path_: []const u8, open_flags: std.fs.File.OpenFlags) !std.fs.File { if (comptime Environment.isWindows) { - var flags: Mode = 0; + var flags: i32 = 0; switch (open_flags.mode) { .read_only => flags |= O.RDONLY, .write_only => flags |= O.WRONLY, @@ -1468,10 +1468,10 @@ pub fn getFdPathW(fd_: anytype, buf: *WPathBuffer) ![]u16 { fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { switch (@typeInfo(@TypeOf(ptr))) { - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => switch (@typeInfo(ptr_info.child)) { - .Array => |array_info| { - if (array_info.sentinel) |sentinel_ptr| { + .pointer => |ptr_info| switch (ptr_info.size) { + .one => switch (@typeInfo(ptr_info.child)) { + .array => |array_info| { + if (array_info.sentinel_ptr) |sentinel_ptr| { const sentinel = @as(*align(1) const array_info.child, @ptrCast(sentinel_ptr)).*; if (sentinel == end) { return std.mem.indexOfSentinel(array_info.child, end, ptr); @@ -1481,7 +1481,7 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { }, else => {}, }, - .Many => if (ptr_info.sentinel) |sentinel_ptr| { + .many => if (ptr_info.sentinel_ptr) |sentinel_ptr| { const sentinel = @as(*align(1) const ptr_info.child, @ptrCast(sentinel_ptr)).*; // We may be looking for something other than the sentinel, // but iterating past the sentinel would be a bug so we need @@ -1490,12 +1490,12 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { while (ptr[i] != end and ptr[i] != sentinel) i += 1; return i; }, - .C => { + .c => { assert(ptr != null); return std.mem.indexOfSentinel(ptr_info.child, end, ptr); }, - .Slice => { - if (ptr_info.sentinel) |sentinel_ptr| { + .slice => { + if (ptr_info.sentinel_ptr) |sentinel_ptr| { const sentinel = @as(*align(1) const ptr_info.child, @ptrCast(sentinel_ptr)).*; if (sentinel == end) { return std.mem.indexOfSentinel(ptr_info.child, sentinel, ptr); @@ -1512,51 +1512,51 @@ fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize { /// Helper for the return type of sliceTo() fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type { switch (@typeInfo(T)) { - .Optional => |optional_info| { + .optional => |optional_info| { return ?SliceTo(optional_info.child, end); }, - .Pointer => |ptr_info| { + .pointer => |ptr_info| { var new_ptr_info = ptr_info; - new_ptr_info.size = .Slice; + new_ptr_info.size = .slice; switch (ptr_info.size) { - .One => switch (@typeInfo(ptr_info.child)) { - .Array => |array_info| { + .one => switch (@typeInfo(ptr_info.child)) { + .array => |array_info| { new_ptr_info.child = array_info.child; // The return type must only be sentinel terminated if we are guaranteed // to find the value searched for, which is only the case if it matches // the sentinel of the type passed. - if (array_info.sentinel) |sentinel_ptr| { + if (array_info.sentinel_ptr) |sentinel_ptr| { const sentinel = @as(*align(1) const array_info.child, @ptrCast(sentinel_ptr)).*; if (end == sentinel) { - new_ptr_info.sentinel = &end; + new_ptr_info.sentinel_ptr = &end; } else { - new_ptr_info.sentinel = null; + new_ptr_info.sentinel_ptr = null; } } }, else => {}, }, - .Many, .Slice => { + .many, .slice => { // The return type must only be sentinel terminated if we are guaranteed // to find the value searched for, which is only the case if it matches // the sentinel of the type passed. - if (ptr_info.sentinel) |sentinel_ptr| { + if (ptr_info.sentinel_ptr) |sentinel_ptr| { const sentinel = @as(*align(1) const ptr_info.child, @ptrCast(sentinel_ptr)).*; if (end == sentinel) { - new_ptr_info.sentinel = &end; + new_ptr_info.sentinel_ptr = &end; } else { - new_ptr_info.sentinel = null; + new_ptr_info.sentinel_ptr = null; } } }, - .C => { - new_ptr_info.sentinel = &end; + .c => { + new_ptr_info.sentinel_ptr = &end; // C pointers are always allowzero, but we don't want the return type to be. assert(new_ptr_info.is_allowzero); new_ptr_info.is_allowzero = false; }, } - return @Type(.{ .Pointer = new_ptr_info }); + return @Type(.{ .pointer = new_ptr_info }); }, else => {}, } @@ -1571,14 +1571,14 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type { /// Pointer properties such as mutability and alignment are preserved. /// C pointers are assumed to be non-null. pub fn sliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) SliceTo(@TypeOf(ptr), end) { - if (@typeInfo(@TypeOf(ptr)) == .Optional) { + if (@typeInfo(@TypeOf(ptr)) == .optional) { const non_null = ptr orelse return null; return sliceTo(non_null, end); } const Result = SliceTo(@TypeOf(ptr), end); const length = lenSliceTo(ptr, end); - const ptr_info = @typeInfo(Result).Pointer; - if (ptr_info.sentinel) |s_ptr| { + const ptr_info = @typeInfo(Result).pointer; + if (ptr_info.sentinel_ptr) |s_ptr| { const s = @as(*align(1) const ptr_info.child, @ptrCast(s_ptr)).*; return ptr[0..length :s]; } else { @@ -1598,7 +1598,7 @@ pub fn cstring(input: []const u8) [:0]const u8 { return @as([*:0]const u8, @ptrCast(input.ptr))[0..input.len :0]; } -pub const Semver = @import("./install/semver.zig"); +pub const Semver = @import("./semver.zig"); pub const ImportRecord = @import("./import_record.zig").ImportRecord; pub const ImportKind = @import("./import_record.zig").ImportKind; @@ -1693,7 +1693,6 @@ pub const failing_allocator = std.mem.Allocator{ .ptr = undefined, .vtable = &.{ var __reload_in_progress__ = std.atomic.Value(bool).init(false); threadlocal var __reload_in_progress__on_current_thread = false; pub fn isProcessReloadInProgressOnAnotherThread() bool { - @fence(.acquire); return __reload_in_progress__.load(.monotonic) and !__reload_in_progress__on_current_thread; } @@ -1833,7 +1832,7 @@ pub fn reloadProcess( } } else if (comptime Environment.isPosix) { const on_before_reload_process_linux = struct { - pub extern "C" fn on_before_reload_process_linux() void; + pub extern "c" fn on_before_reload_process_linux() void; }.on_before_reload_process_linux; on_before_reload_process_linux(); @@ -2305,7 +2304,7 @@ pub fn initArgv(allocator: std.mem.Allocator) !void { // Updates in Zig v0.12 related to Windows cmd line parsing may fix this, // see (here: https://ziglang.org/download/0.12.0/release-notes.html#Windows-Command-Line-Argument-Parsing), // so this may only need to be a temporary workaround. - const cmdline_ptr = std.os.windows.kernel32.GetCommandLineW(); + const cmdline_ptr = bun.windows.GetCommandLineW(); var length: c_int = 0; // As per the documentation: @@ -2323,7 +2322,7 @@ pub fn initArgv(allocator: std.mem.Allocator) !void { }; const argvu16 = argvu16_ptr[0..@intCast(length)]; - const out_argv = try allocator.alloc([:0]u8, @intCast(length)); + const out_argv = try allocator.alloc([:0]const u8, @intCast(length)); var string_builder = StringBuilder{}; for (argvu16) |argraw| { @@ -2559,7 +2558,7 @@ pub const win32 = struct { @memset(std.mem.asBytes(procinfo), 0); const rc = w.kernel32.CreateProcessW( image_pathZ.ptr, - w.kernel32.GetCommandLineW(), + bun.windows.GetCommandLineW(), null, null, 1, @@ -2601,7 +2600,7 @@ pub const FDTag = enum { const fd = toFD(fd_); const T = @TypeOf(fd_); if (comptime Environment.isWindows) { - if (@typeInfo(T) == .Int or @typeInfo(T) == .ComptimeInt) { + if (@typeInfo(T) == .int or @typeInfo(T) == .comptime_int) { switch (fd_) { 0 => return .stdin, 1 => return .stdout, @@ -2672,7 +2671,7 @@ pub fn serializable(input: anytype) @TypeOf(input) { const T = @TypeOf(input); comptime { if (trait.isExternContainer(T)) { - if (@typeInfo(T) == .Union) { + if (@typeInfo(T) == .@"union") { @compileError("Extern unions must be serialized with serializableInto"); } } @@ -3045,12 +3044,12 @@ pub const Dirname = struct { }; pub noinline fn outOfMemory() noreturn { - @setCold(true); + @branchHint(.cold); crash_handler.crashHandler(.out_of_memory, null, @returnAddress()); } pub fn todoPanic(src: std.builtin.SourceLocation, comptime format: string, args: anytype) noreturn { - @setCold(true); + @branchHint(.cold); bun.Analytics.Features.todo_panic = 1; Output.panic("TODO: " ++ format ++ " ({s}:{d})", args ++ .{ src.file, src.line }); } @@ -3086,10 +3085,11 @@ pub inline fn new(comptime T: type, init: T) *T { break :ptr ptr; }; - if (comptime Environment.allow_assert) { - const logAlloc = Output.scoped(.alloc, @hasDecl(T, "logAllocations")); - logAlloc("new({s}) = {*}", .{ meta.typeName(T), ptr }); - } + // TODO:: + // if (comptime Environment.allow_assert) { + // const logAlloc = Output.scoped(.alloc, @hasDecl(T, "logAllocations")); + // logAlloc("new({s}) = {*}", .{ meta.typeName(T), ptr }); + // } return ptr; } @@ -3132,21 +3132,20 @@ pub fn New(comptime T: type) type { /// Reference-counted heap-allocated instance value. /// /// `ref_count` is expected to be defined on `T` with a default value set to `1` -pub fn NewRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: *T) void) type { +pub fn NewRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: *T) void, debug_name: ?[:0]const u8) type { if (!@hasField(T, "ref_count")) { @compileError("Expected a field named \"ref_count\" with a default value of 1 on " ++ @typeName(T)); } for (std.meta.fields(T)) |field| { if (strings.eqlComptime(field.name, "ref_count")) { - if (field.default_value == null) { + if (field.default_value_ptr == null) { @compileError("Expected a field named \"ref_count\" with a default value of 1 on " ++ @typeName(T)); } } } - const output_name: []const u8 = if (@hasDecl(T, "DEBUG_REFCOUNT_NAME")) T.DEBUG_REFCOUNT_NAME else meta.typeBaseName(@typeName(T)); - + const output_name = debug_name orelse meta.typeBaseName(@typeName(T)); const log = Output.scoped(output_name, true); return struct { @@ -3165,11 +3164,18 @@ pub fn NewRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: *T) void) } pub fn deref(self: *T) void { - if (Environment.isDebug) log("0x{x} deref {d} - 1 = {d}", .{ @intFromPtr(self), self.ref_count, self.ref_count - 1 }); + const ref_count = self.ref_count; + if (Environment.isDebug) { + if (ref_count == 0 or ref_count == std.math.maxInt(@TypeOf(ref_count))) { + @panic("Use after-free detected on " ++ output_name); + } + } - self.ref_count -= 1; + if (Environment.isDebug) log("0x{x} deref {d} - 1 = {d}", .{ @intFromPtr(self), ref_count, ref_count - 1 }); - if (self.ref_count == 0) { + self.ref_count = ref_count - 1; + + if (ref_count == 1) { if (comptime deinit_fn) |deinit| { deinit(self); } else { @@ -3192,21 +3198,20 @@ pub fn NewRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: *T) void) }; } -pub fn NewThreadSafeRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: *T) void) type { +pub fn NewThreadSafeRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: *T) void, debug_name: ?[:0]const u8) type { if (!@hasField(T, "ref_count")) { @compileError("Expected a field named \"ref_count\" with a default value of 1 on " ++ @typeName(T)); } for (std.meta.fields(T)) |field| { if (strings.eqlComptime(field.name, "ref_count")) { - if (field.default_value == null) { + if (field.default_value_ptr == null) { @compileError("Expected a field named \"ref_count\" with a default value of 1 on " ++ @typeName(T)); } } } - const output_name: []const u8 = if (@hasDecl(T, "DEBUG_REFCOUNT_NAME")) T.DEBUG_REFCOUNT_NAME else meta.typeBaseName(@typeName(T)); - + const output_name = debug_name orelse meta.typeBaseName(@typeName(T)); const log = Output.scoped(output_name, true); return struct { @@ -3253,7 +3258,7 @@ pub fn NewThreadSafeRefCounted(comptime T: type, comptime deinit_fn: ?fn (self: pub fn exitThread() noreturn { const exiter = struct { - pub extern "C" fn pthread_exit(?*anyopaque) noreturn; + pub extern "c" fn pthread_exit(?*anyopaque) noreturn; pub extern "kernel32" fn ExitThread(windows.DWORD) noreturn; }; @@ -3297,7 +3302,7 @@ const errno_map = errno_map: { }; pub fn errnoToZigErr(err: anytype) anyerror { - var num = if (@typeInfo(@TypeOf(err)) == .Enum) + var num = if (@typeInfo(@TypeOf(err)) == .@"enum") @intFromEnum(err) else err; @@ -3330,13 +3335,13 @@ pub fn iterateDir(dir: std.fs.Dir) DirIterator.Iterator { } fn ReinterpretSliceType(comptime T: type, comptime slice: type) type { - const is_const = @typeInfo(slice).Pointer.is_const; + const is_const = @typeInfo(slice).pointer.is_const; return if (is_const) []const T else []T; } /// Zig has a todo for @ptrCast changing the `.len`. This is the workaround pub fn reinterpretSlice(comptime T: type, slice: anytype) ReinterpretSliceType(T, @TypeOf(slice)) { - const is_const = @typeInfo(@TypeOf(slice)).Pointer.is_const; + const is_const = @typeInfo(@TypeOf(slice)).pointer.is_const; const bytes = std.mem.sliceAsBytes(slice); const new_ptr = @as(if (is_const) [*]const T else [*]T, @ptrCast(@alignCast(bytes.ptr))); return new_ptr[0..@divTrunc(bytes.len, @sizeOf(T))]; @@ -3532,23 +3537,23 @@ pub const handleErrorReturnTrace = crash_handler.handleErrorReturnTrace; noinline fn assertionFailure() noreturn { if (@inComptime()) { @compileError("assertion failure"); + } else { + @branchHint(.cold); + Output.panic("Internal assertion failure", .{}); } - - @setCold(true); - Output.panic("Internal assertion failure", .{}); } noinline fn assertionFailureWithLocation(src: std.builtin.SourceLocation) noreturn { if (@inComptime()) { @compileError("assertion failure"); + } else { + @branchHint(.cold); + Output.panic("Internal assertion failure {s}:{d}:{d}", .{ + src.file, + src.line, + src.column, + }); } - - @setCold(true); - Output.panic("Internal assertion failure {s}:{d}:{d}", .{ - src.file, - src.line, - src.column, - }); } pub fn debugAssert(cheap_value_only_plz: bool) callconv(callconv_inline) void { @@ -3618,14 +3623,14 @@ pub fn getRoughTickCount() timespec { .sec = 0, }; const clocky = struct { - pub var clock_id: i32 = 0; + pub var clock_id: std.c.CLOCK = .REALTIME; pub fn get() void { var res = timespec{}; - _ = std.c.clock_getres(C.CLOCK_MONOTONIC_RAW_APPROX, @ptrCast(&res)); + _ = std.c.clock_getres(.MONOTONIC_RAW_APPROX, @ptrCast(&res)); if (res.ms() <= 1) { - clock_id = C.CLOCK_MONOTONIC_RAW_APPROX; + clock_id = .MONOTONIC_RAW_APPROX; } else { - clock_id = C.CLOCK_MONOTONIC_RAW; + clock_id = .MONOTONIC_RAW; } } @@ -3644,14 +3649,14 @@ pub fn getRoughTickCount() timespec { .sec = 0, }; const clocky = struct { - pub var clock_id: i32 = 0; + pub var clock_id: std.os.linux.CLOCK = .REALTIME; pub fn get() void { var res = timespec{}; - _ = std.os.linux.clock_getres(std.os.linux.CLOCK.MONOTONIC_COARSE, @ptrCast(&res)); + _ = std.os.linux.clock_getres(.MONOTONIC_COARSE, @ptrCast(&res)); if (res.ms() <= 1) { - clock_id = std.os.linux.CLOCK.MONOTONIC_COARSE; + clock_id = .MONOTONIC_COARSE; } else { - clock_id = std.os.linux.CLOCK.MONOTONIC_RAW; + clock_id = .MONOTONIC_RAW; } } @@ -3812,7 +3817,7 @@ pub const UUID = @import("./bun.js/uuid.zig"); /// call a first element '0' or '1' which makes integer type ambiguous. pub fn OrdinalT(comptime Int: type) type { return enum(Int) { - invalid = switch (@typeInfo(Int).Int.signedness) { + invalid = switch (@typeInfo(Int).int.signedness) { .unsigned => std.math.maxInt(Int), .signed => -1, }, @@ -3880,11 +3885,11 @@ pub const bake = @import("bake/bake.zig"); /// like std.enums.tagName, except it doesn't lose the sentinel value. pub fn tagName(comptime Enum: type, value: Enum) ?[:0]const u8 { - return inline for (@typeInfo(Enum).Enum.fields) |f| { + return inline for (@typeInfo(Enum).@"enum".fields) |f| { if (@intFromEnum(value) == f.value) break f.name; } else null; } -extern "C" fn Bun__ramSize() usize; +extern "c" fn Bun__ramSize() usize; pub fn getTotalMemorySize() usize { return Bun__ramSize(); } @@ -4020,7 +4025,7 @@ pub fn GenericIndex(backing_int: type, uid: anytype) type { return @enumFromInt(int); } - /// Prefer this over @intFromEnum because of type confusion with `.Optional` + /// Prefer this over @intFromEnum because of type confusion with `.optional` pub inline fn get(i: @This()) backing_int { bun.assert(@intFromEnum(i) != null_value); // memory corruption return @intFromEnum(i); @@ -4121,7 +4126,7 @@ pub fn once(comptime f: anytype) Once(f) { /// It is undefined behavior if `f` re-enters the same Once instance. pub fn Once(comptime f: anytype) type { return struct { - const Return = @typeInfo(@TypeOf(f)).Fn.return_type.?; + const Return = @typeInfo(@TypeOf(f)).@"fn".return_type.?; done: bool = false, payload: Return = undefined, @@ -4139,7 +4144,7 @@ pub fn Once(comptime f: anytype) type { } fn callSlow(self: *@This(), args: std.meta.ArgsTuple(@TypeOf(f))) Return { - @setCold(true); + @branchHint(.cold); self.mutex.lock(); defer self.mutex.unlock(); @@ -4158,7 +4163,7 @@ pub fn Once(comptime f: anytype) type { /// `val` must be a pointer to an optional type (e.g. `*?T`) /// /// This function takes the value out of the optional, replacing it with null, and returns the value. -pub inline fn take(val: anytype) ?bun.meta.OptionalChild(@TypeOf(val)) { +pub inline fn take(val: anytype) ?@typeInfo(@typeInfo(@TypeOf(val)).pointer.child).optional.child { if (val.*) |v| { val.* = null; return v; @@ -4182,11 +4187,11 @@ pub inline fn wrappingNegation(val: anytype) @TypeOf(val) { fn assertNoPointers(T: type) void { switch (@typeInfo(T)) { - .Pointer => @compileError("no pointers!"), - inline .Struct, .Union => |s| for (s.fields) |field| { + .pointer => @compileError("no pointers!"), + inline .@"struct", .@"union" => |s| for (s.fields) |field| { assertNoPointers(field.type); }, - .Array => |a| assertNoPointers(a.child), + .array => |a| assertNoPointers(a.child), else => {}, } } @@ -4197,7 +4202,7 @@ pub inline fn writeAnyToHasher(hasher: anytype, thing: anytype) void { } pub inline fn isComptimeKnown(x: anytype) bool { - return comptime @typeInfo(@TypeOf(.{x})).Struct.fields[0].is_comptime; + return comptime @typeInfo(@TypeOf(.{x})).@"struct".fields[0].is_comptime; } pub inline fn itemOrNull(comptime T: type, slice: []const T, index: usize) ?T { @@ -4291,7 +4296,7 @@ pub const StackCheck = struct { Bun__StackCheck__initialize(); } - extern "C" fn Bun__StackCheck__getMaxStack() usize; + extern "c" fn Bun__StackCheck__getMaxStack() usize; fn getStackEnd() usize { return Bun__StackCheck__getMaxStack(); } @@ -4314,7 +4319,7 @@ pub const StackCheck = struct { // Workaround for lack of branch hints. pub noinline fn throwStackOverflow() StackOverflow!void { - @setCold(true); + @branchHint(.cold); return error.StackOverflow; } const StackOverflow = error{StackOverflow}; diff --git a/src/bun_js.zig b/src/bun_js.zig index 9c783ade3dce57..0a96ee2a1b3bc2 100644 --- a/src/bun_js.zig +++ b/src/bun_js.zig @@ -42,6 +42,7 @@ pub const Run = struct { entry_path: string, arena: Arena, any_unhandled: bool = false, + is_html_entrypoint: bool = false, pub fn bootStandalone(ctx: Command.Context, entry_path: string, graph: bun.StandaloneModuleGraph) !void { JSC.markBinding(@src()); @@ -155,7 +156,7 @@ pub const Run = struct { } fn bootBunShell(ctx: Command.Context, entry_path: []const u8) !bun.shell.ExitCode { - @setCold(true); + @branchHint(.cold); // this is a hack: make dummy bundler so we can use its `.runEnvLoader()` function to populate environment variables probably should split out the functionality var bundle = try bun.Transpiler.init( @@ -170,7 +171,7 @@ pub const Run = struct { return bun.shell.Interpreter.initAndRunFromFile(ctx, mini, entry_path); } - pub fn boot(ctx: Command.Context, entry_path: string) !void { + pub fn boot(ctx: Command.Context, entry_path: string, loader: ?bun.options.Loader) !void { JSC.markBinding(@src()); if (!ctx.debug.loaded_bunfig) { @@ -277,6 +278,8 @@ pub const Run = struct { doPreconnect(ctx.runtime_options.preconnect); + vm.main_is_html_entrypoint = (loader orelse vm.transpiler.options.loader(std.fs.path.extension(entry_path))) == .html; + const callback = OpaqueWrap(Run, Run.start); vm.global.vm().holdAPILock(&run, callback); } @@ -444,7 +447,7 @@ pub const Run = struct { ); } - if (!JSC.is_bindgen) JSC.napi.fixDeadCodeElimination(); + JSC.napi.fixDeadCodeElimination(); vm.globalExit(); } @@ -482,7 +485,7 @@ pub export fn Bun__onRejectEntryPointResult(global: *JSC.JSGlobalObject, callfra } noinline fn dumpBuildError(vm: *JSC.VirtualMachine) void { - @setCold(true); + @branchHint(.cold); Output.flush(); @@ -498,7 +501,7 @@ noinline fn dumpBuildError(vm: *JSC.VirtualMachine) void { } pub noinline fn failWithBuildError(vm: *JSC.VirtualMachine) noreturn { - @setCold(true); + @branchHint(.cold); dumpBuildError(vm); Global.exit(1); } diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 08af47c764ec64..cbe69cafde504a 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -901,7 +901,14 @@ pub const BundleV2 = struct { task.tree_shaking = this.linker.options.tree_shaking; task.is_entry_point = is_entry_point; task.known_target = target; - task.jsx.development = this.bundlerForTarget(target).options.jsx.development; + { + const bundler = this.bundlerForTarget(target); + task.jsx.development = switch (bundler.options.force_node_env) { + .development => true, + .production => false, + .unspecified => bundler.options.jsx.development, + }; + } // Handle onLoad plugins as entry points if (!this.enqueueOnLoadPluginIfNeeded(task)) { @@ -1707,7 +1714,7 @@ pub const BundleV2 = struct { ref_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(1), started_at_ns: u64 = 0, - pub usingnamespace bun.NewThreadSafeRefCounted(JSBundleCompletionTask, @This().deinit); + pub usingnamespace bun.NewThreadSafeRefCounted(JSBundleCompletionTask, _deinit, null); pub fn configureBundler( completion: *JSBundleCompletionTask, @@ -1741,6 +1748,9 @@ pub const BundleV2 = struct { ); transpiler.options.env.behavior = config.env_behavior; transpiler.options.env.prefix = config.env_prefix.slice(); + if (config.force_node_env != .unspecified) { + transpiler.options.force_node_env = config.force_node_env; + } transpiler.options.entry_points = config.entry_points.keys(); transpiler.options.jsx = config.jsx; @@ -1785,7 +1795,7 @@ pub const BundleV2 = struct { pub const TaskCompletion = bun.JSC.AnyTask.New(JSBundleCompletionTask, onComplete); - pub fn deinit(this: *JSBundleCompletionTask) void { + fn _deinit(this: *JSBundleCompletionTask) void { this.result.deinit(); this.log.deinit(); this.poll_ref.disable(); @@ -2863,7 +2873,11 @@ pub const BundleV2 = struct { resolve_task.secondary_path_for_commonjs_interop = secondary_path_to_copy; resolve_task.known_target = target; resolve_task.jsx = resolve_result.jsx; - resolve_task.jsx.development = this.bundlerForTarget(target).options.jsx.development; + resolve_task.jsx.development = switch (transpiler.options.force_node_env) { + .development => true, + .production => false, + .unspecified => transpiler.options.jsx.development, + }; // Figure out the loader. { @@ -3530,7 +3544,7 @@ pub const ParseTask = struct { }; }; - const debug = Output.scoped(.ParseTask, false); + const debug = Output.scoped(.ParseTask, true); pub fn init(resolve_result: *const _resolver.Result, source_index: Index, ctx: *BundleV2) ParseTask { return .{ @@ -7533,7 +7547,7 @@ pub const LinkerContext = struct { continue; } - _ = this.validateTLA(id, tla_keywords, tla_checks, input_files, import_records, flags); + _ = this.validateTLA(id, tla_keywords, tla_checks, input_files, import_records, flags, import_records_list); for (import_records) |record| { if (!record.source_index.isValid()) { @@ -11015,6 +11029,7 @@ pub const LinkerContext = struct { input_files: []Logger.Source, import_records: []ImportRecord, meta_flags: []JSMeta.Flags, + ast_import_records: []bun.BabyList(ImportRecord), ) js_ast.TlaCheck { var result_tla_check: *js_ast.TlaCheck = &tla_checks[source_index]; @@ -11026,7 +11041,7 @@ pub const LinkerContext = struct { for (import_records, 0..) |record, import_record_index| { if (Index.isValid(record.source_index) and (record.kind == .require or record.kind == .stmt)) { - const parent = c.validateTLA(record.source_index.get(), tla_keywords, tla_checks, input_files, import_records, meta_flags); + const parent = c.validateTLA(record.source_index.get(), tla_keywords, tla_checks, input_files, import_records, meta_flags, ast_import_records); if (Index.isInvalid(Index.init(parent.parent))) { continue; } @@ -11053,9 +11068,11 @@ pub const LinkerContext = struct { const parent_source_index = other_source_index; if (parent_result_tla_keyword.len > 0) { - tla_pretty_path = input_files[other_source_index].path.pretty; + const source = input_files[other_source_index]; + tla_pretty_path = source.path.pretty; notes.append(Logger.Data{ .text = std.fmt.allocPrint(c.allocator, "The top-level await in {s} is here:", .{tla_pretty_path}) catch bun.outOfMemory(), + .location = .initOrNull(&source, parent_result_tla_keyword), }) catch bun.outOfMemory(); break; } @@ -11074,6 +11091,7 @@ pub const LinkerContext = struct { input_files[parent_source_index].path.pretty, input_files[other_source_index].path.pretty, }) catch bun.outOfMemory(), + .location = .initOrNull(&input_files[parent_source_index], ast_import_records[parent_source_index].slice()[tla_checks[parent_source_index].import_record_index].range), }) catch bun.outOfMemory(); } @@ -13559,6 +13577,7 @@ pub const LinkerContext = struct { .js; if (loader.isJavaScriptLike()) { + JSC.VirtualMachine.is_bundler_thread_for_bytecode_cache = true; JSC.initialize(false); var fdpath: bun.PathBuffer = undefined; var source_provider_url = try bun.String.createFormat("{s}" ++ bun.bytecode_extension, .{chunk.final_rel_path}); @@ -13903,6 +13922,7 @@ pub const LinkerContext = struct { .js; if (loader.isJavaScriptLike()) { + JSC.VirtualMachine.is_bundler_thread_for_bytecode_cache = true; JSC.initialize(false); var fdpath: bun.PathBuffer = undefined; var source_provider_url = try bun.String.createFormat("{s}" ++ bun.bytecode_extension, .{chunk.final_rel_path}); @@ -14776,7 +14796,7 @@ pub const LinkerContext = struct { Part.SymbolUseMap, c.allocator, .{ - .{ wrapper_ref, .{ .count_estimate = 1 } }, + .{ wrapper_ref, Symbol.Use{ .count_estimate = 1 } }, }, ) catch unreachable, .declared_symbols = js_ast.DeclaredSymbol.List.fromSlice( @@ -14833,10 +14853,10 @@ pub const LinkerContext = struct { const part_index = c.graph.addPartToFile( source_index, .{ - .symbol_uses = bun.from( + .symbol_uses = bun.fromMapLike( Part.SymbolUseMap, c.allocator, - .{ + &.{ .{ wrapper_ref, .{ .count_estimate = 1 } }, }, ) catch unreachable, diff --git a/src/bunfig.zig b/src/bunfig.zig index 79dc4c07ccb69d..1951b03630d4d9 100644 --- a/src/bunfig.zig +++ b/src/bunfig.zig @@ -656,7 +656,29 @@ pub const Bunfig = struct { } }; + // TODO: accept entire config object. this.bunfig.serve_plugins = plugins; + if (serve_obj.get("minify")) |minify| { + if (minify.asBool()) |value| { + this.bunfig.serve_minify_syntax = value; + this.bunfig.serve_minify_whitespace = value; + this.bunfig.serve_minify_identifiers = value; + } else if (minify.isObject()) { + if (minify.get("syntax")) |syntax| { + this.bunfig.serve_minify_syntax = syntax.asBool() orelse false; + } + + if (minify.get("whitespace")) |whitespace| { + this.bunfig.serve_minify_whitespace = whitespace.asBool() orelse false; + } + + if (minify.get("identifiers")) |identifiers| { + this.bunfig.serve_minify_identifiers = identifiers.asBool() orelse false; + } + } else { + try this.addError(minify.loc, "Expected minify to be boolean or object"); + } + } this.bunfig.bunfig_path = bun.default_allocator.dupe(u8, this.source.path.text) catch bun.outOfMemory(); } } diff --git a/src/c-headers-for-zig.h b/src/c-headers-for-zig.h index e698aadec6ad6d..6292d6ffcb5b22 100644 --- a/src/c-headers-for-zig.h +++ b/src/c-headers-for-zig.h @@ -25,6 +25,7 @@ #if DARWIN #include #include +#include #elif LINUX #include #include diff --git a/src/c.zig b/src/c.zig index 98414cbfbde47f..3b4b59383c4220 100644 --- a/src/c.zig +++ b/src/c.zig @@ -88,9 +88,9 @@ pub fn lstat_absolute(path: [:0]const u8) !Stat { else => Kind.unknown, }, }, - .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, - .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, - .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, + .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, + .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, + .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, }; } @@ -417,7 +417,7 @@ pub fn _dlsym(handle: ?*anyopaque, name: [:0]const u8) ?*anyopaque { } pub fn dlsymWithHandle(comptime Type: type, comptime name: [:0]const u8, comptime handle_getter: fn () ?*anyopaque) ?Type { - if (comptime @typeInfo(Type) != .Pointer) { + if (comptime @typeInfo(Type) != .pointer) { @compileError("dlsym must be a pointer type (e.g. ?const *fn()). Received " ++ @typeName(Type) ++ "."); } @@ -480,7 +480,7 @@ pub extern fn memmove(dest: [*]u8, src: [*]const u8, n: usize) void; // https://man7.org/linux/man-pages/man3/fmod.3.html pub extern fn fmod(f64, f64) f64; -pub fn dlopen(filename: [:0]const u8, flags: i32) ?*anyopaque { +pub fn dlopen(filename: [:0]const u8, flags: C.RTLD) ?*anyopaque { if (comptime Environment.isWindows) { return bun.windows.LoadLibraryA(filename); } @@ -488,11 +488,11 @@ pub fn dlopen(filename: [:0]const u8, flags: i32) ?*anyopaque { return std.c.dlopen(filename, flags); } -pub extern "C" fn Bun__ttySetMode(fd: c_int, mode: c_int) c_int; +pub extern "c" fn Bun__ttySetMode(fd: c_int, mode: c_int) c_int; -pub extern "C" fn bun_initialize_process() void; -pub extern "C" fn bun_restore_stdio() void; -pub extern "C" fn open_as_nonblocking_tty(i32, i32) i32; +pub extern "c" fn bun_initialize_process() void; +pub extern "c" fn bun_restore_stdio() void; +pub extern "c" fn open_as_nonblocking_tty(i32, i32) i32; pub extern fn strlen(ptr: [*c]const u8) usize; diff --git a/src/cli.zig b/src/cli.zig index 36407e2bedd778..721ba19eb3705f 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -47,6 +47,7 @@ pub var start_time: i128 = undefined; const Bunfig = @import("./bunfig.zig").Bunfig; const OOM = bun.OOM; +export var Bun__Node__ZeroFillBuffers = false; export var Bun__Node__ProcessNoDeprecation = false; export var Bun__Node__ProcessThrowDeprecation = false; @@ -108,7 +109,7 @@ const ColonListType = @import("./cli/colon_list_type.zig").ColonListType; pub const LoaderColonList = ColonListType(Api.Loader, Arguments.loader_resolver); pub const DefineColonList = ColonListType(string, Arguments.noop_resolver); fn invalidTarget(diag: *clap.Diagnostic, _target: []const u8) noreturn { - @setCold(true); + @branchHint(.cold); diag.name.long = "target"; diag.arg = _target; diag.report(Output.errorWriter(), error.InvalidTarget) catch {}; @@ -241,6 +242,7 @@ pub const Arguments = struct { clap.parseParam("--no-deprecation Suppress all reporting of the custom deprecation.") catch unreachable, clap.parseParam("--throw-deprecation Determine whether or not deprecation warnings result in errors.") catch unreachable, clap.parseParam("--title Set the process title") catch unreachable, + clap.parseParam("--zero-fill-buffers Boolean to force Buffer.allocUnsafe(size) to be zero-filled.") catch unreachable, }; const auto_or_run_params = [_]ParamType{ @@ -295,12 +297,12 @@ pub const Arguments = struct { clap.parseParam("--minify-syntax Minify syntax and inline data") catch unreachable, clap.parseParam("--minify-whitespace Minify whitespace") catch unreachable, clap.parseParam("--minify-identifiers Minify identifiers") catch unreachable, - clap.parseParam("--css-chunking Chunk CSS files together to reduce duplicated CSS loaded in a browser. Only has an affect when multiple entrypoints import CSS") catch unreachable, + clap.parseParam("--css-chunking Chunk CSS files together to reduce duplicated CSS loaded in a browser. Only has an effect when multiple entrypoints import CSS") catch unreachable, clap.parseParam("--dump-environment-variables") catch unreachable, clap.parseParam("--conditions ... Pass custom conditions to resolve") catch unreachable, clap.parseParam("--app (EXPERIMENTAL) Build a web app for production using Bun Bake.") catch unreachable, clap.parseParam("--server-components (EXPERIMENTAL) Enable server components") catch unreachable, - clap.parseParam("--env Inline environment variables into the bundle as process.env.${name}. Defaults to 'inline'. To inline environment variables matching a prefix, use my prefix like 'FOO_PUBLIC_*'. To disable, use 'disable'. In Bun v1.2+, the default is 'disable'.") catch unreachable, + clap.parseParam("--env Inline environment variables into the bundle as process.env.${name}. Defaults to 'disable'. To inline environment variables matching a prefix, use my prefix like 'FOO_PUBLIC_*'.") catch unreachable, clap.parseParam("--windows-hide-console When using --compile targeting Windows, prevent a Command prompt from opening alongside the executable") catch unreachable, clap.parseParam("--windows-icon When using --compile targeting Windows, assign an executable icon") catch unreachable, } ++ if (FeatureFlags.bake_debugging_features) [_]ParamType{ @@ -813,6 +815,9 @@ pub const Arguments = struct { if (args.option("--title")) |title| { Bun__Node__ProcessTitle = title; } + if (args.flag("--zero-fill-buffers")) { + Bun__Node__ZeroFillBuffers = true; + } } if (opts.port != null and opts.origin == null) { @@ -1245,7 +1250,7 @@ const AutoCommand = struct { pub const HelpCommand = struct { pub fn exec(allocator: std.mem.Allocator) !void { - @setCold(true); + @branchHint(.cold); execWithReason(allocator, .explicit); } @@ -1339,7 +1344,7 @@ pub const HelpCommand = struct { ; pub fn printWithReason(comptime reason: Reason, show_all_flags: bool) void { - var rand_state = std.rand.DefaultPrng.init(@as(u64, @intCast(@max(std.time.milliTimestamp(), 0)))); + var rand_state = std.Random.DefaultPrng.init(@as(u64, @intCast(@max(std.time.milliTimestamp(), 0)))); const rand = rand_state.random(); const package_x_i = rand.uintAtMost(usize, packages_to_x_filler.len - 1); @@ -1383,7 +1388,7 @@ pub const HelpCommand = struct { } pub fn execWithReason(_: std.mem.Allocator, comptime reason: Reason) void { - @setCold(true); + @branchHint(.cold); printWithReason(reason, false); if (reason == .invalid_command) { @@ -1395,7 +1400,7 @@ pub const HelpCommand = struct { pub const ReservedCommand = struct { pub fn exec(_: std.mem.Allocator) !void { - @setCold(true); + @branchHint(.cold); const command_name = for (bun.argv[1..]) |arg| { if (arg.len > 1 and arg[0] == '-') continue; break arg; @@ -2191,7 +2196,7 @@ pub const Command = struct { var entry_point_buf: [bun.MAX_PATH_BYTES + trigger.len]u8 = undefined; const cwd = try std.posix.getcwd(&entry_point_buf); @memcpy(entry_point_buf[cwd.len..][0..trigger.len], trigger); - try BunJS.Run.boot(ctx, entry_point_buf[0 .. cwd.len + trigger.len]); + try BunJS.Run.boot(ctx, entry_point_buf[0 .. cwd.len + trigger.len], null); return; } @@ -2646,13 +2651,13 @@ pub const Command = struct { }; pub fn printVersionAndExit() noreturn { - @setCold(true); + @branchHint(.cold); Output.writer().writeAll(Global.package_json_version ++ "\n") catch {}; Global.exit(0); } pub fn printRevisionAndExit() noreturn { - @setCold(true); + @branchHint(.cold); Output.writer().writeAll(Global.package_json_version_with_revision ++ "\n") catch {}; Global.exit(0); } diff --git a/src/cli/bunx_command.zig b/src/cli/bunx_command.zig index 3256f302edcbda..e5210fb97d67f9 100644 --- a/src/cli/bunx_command.zig +++ b/src/cli/bunx_command.zig @@ -252,7 +252,7 @@ pub const BunxCommand = struct { } } else { const stat = target_package_json.stat().unwrap() catch break :is_stale true; - break :is_stale std.time.timestamp() - stat.mtime().tv_sec > seconds_cache_valid; + break :is_stale std.time.timestamp() - stat.mtime().sec > seconds_cache_valid; } }; @@ -568,7 +568,7 @@ pub const BunxCommand = struct { if (rc != 0) { break :is_stale true; } - break :is_stale std.time.timestamp() - stat.mtime().tv_sec > seconds_cache_valid; + break :is_stale std.time.timestamp() - stat.mtime().sec > seconds_cache_valid; } }; diff --git a/src/cli/create_command.zig b/src/cli/create_command.zig index bc85f9533113b0..07656cefcfa870 100644 --- a/src/cli/create_command.zig +++ b/src/cli/create_command.zig @@ -99,7 +99,7 @@ fn execTask(allocator: std.mem.Allocator, task_: string, cwd: string, _: string, const task = std.mem.trim(u8, task_, " \n\r\t"); if (task.len == 0) return; - var splitter = std.mem.split(u8, task, " "); + var splitter = std.mem.splitScalar(u8, task, ' '); var count: usize = 0; while (splitter.next() != null) { count += 1; @@ -117,7 +117,7 @@ fn execTask(allocator: std.mem.Allocator, task_: string, cwd: string, _: string, { var i: usize = npm_args; - splitter = std.mem.split(u8, task, " "); + splitter = std.mem.splitScalar(u8, task, ' '); while (splitter.next()) |split| { argv[i] = split; i += 1; @@ -237,7 +237,7 @@ const BUN_CREATE_DIR = ".bun-create"; var home_dir_buf: bun.PathBuffer = undefined; pub const CreateCommand = struct { pub fn exec(ctx: Command.Context, example_tag: Example.Tag, template: []const u8) !void { - @setCold(true); + @branchHint(.cold); Global.configureAllocator(.{ .long_running = false }); HTTP.HTTPThread.init(&.{}); @@ -1367,7 +1367,7 @@ pub const CreateCommand = struct { for (items) |task| { if (task.asString(ctx.allocator)) |task_entry| { // if (needs.bun_bun_for_nextjs or bun_bun_for_react_scripts) { - // var iter = std.mem.split(u8, task_entry, " "); + // var iter = std.mem.splitScalar(u8, task_entry, ' '); // var last_was_bun = false; // while (iter.next()) |current| { // if (strings.eqlComptime(current, "bun")) { @@ -2306,7 +2306,6 @@ const GitHandler = struct { else run(destination, PATH, false) catch false; - @fence(.acquire); success.store( if (outcome) 1 @@ -2318,8 +2317,6 @@ const GitHandler = struct { } pub fn wait() bool { - @fence(.release); - while (success.load(.acquire) == 0) { Futex.wait(&success, 0, 1000) catch continue; } diff --git a/src/cli/filter_run.zig b/src/cli/filter_run.zig index ba1a00ed90b545..7ac33ac5318089 100644 --- a/src/cli/filter_run.zig +++ b/src/cli/filter_run.zig @@ -6,7 +6,7 @@ const std = @import("std"); const Fs = @import("../fs.zig"); const RunCommand = @import("run_command.zig").RunCommand; const DependencyMap = @import("../resolver/package_json.zig").DependencyMap; -const SemverString = @import("../install/semver.zig").String; +const SemverString = bun.Semver.String; const CLI = bun.CLI; const Command = CLI.Command; @@ -409,12 +409,7 @@ const AbortHandler = struct { .mask = std.posix.empty_sigset, .flags = std.posix.SA.SIGINFO | std.posix.SA.RESTART | std.posix.SA.RESETHAND, }; - // if we can't set the handler, we just ignore it - std.posix.sigaction(std.posix.SIG.INT, &action, null) catch |err| { - if (Environment.isDebug) { - Output.warn("Failed to set abort handler: {s}\n", .{@errorName(err)}); - } - }; + std.posix.sigaction(std.posix.SIG.INT, &action, null); } else { const res = bun.windows.SetConsoleCtrlHandler(windowsCtrlHandler, std.os.windows.TRUE); if (res == 0) { diff --git a/src/cli/init_command.zig b/src/cli/init_command.zig index 5cbb0ad95c4b62..9506ef0b55968a 100644 --- a/src/cli/init_command.zig +++ b/src/cli/init_command.zig @@ -68,7 +68,7 @@ pub const InitCommand = struct { /// Create a new asset file, overriding anything that already exists. Known /// assets will have their contents pre-populated; otherwise the file will be empty. fn create(comptime asset_name: []const u8, args: anytype) !void { - const is_template = comptime (@TypeOf(args) != @TypeOf(null)) and @typeInfo(@TypeOf(args)).Struct.fields.len > 0; + const is_template = comptime (@TypeOf(args) != @TypeOf(null)) and @typeInfo(@TypeOf(args)).@"struct".fields.len > 0; return createFull(asset_name, asset_name, "", is_template, args); } @@ -149,7 +149,7 @@ pub const InitCommand = struct { pub fn exec(alloc: std.mem.Allocator, argv: [][:0]const u8) !void { const print_help = brk: { for (argv) |arg| { - if (strings.eqlComptime(arg, "--help")) { + if (strings.eqlComptime(arg, "--help") or strings.eqlComptime(arg, "-h")) { break :brk true; } } diff --git a/src/cli/install_completions_command.zig b/src/cli/install_completions_command.zig index ed9e5d02ace5cf..28109a61319b52 100644 --- a/src/cli/install_completions_command.zig +++ b/src/cli/install_completions_command.zig @@ -303,7 +303,7 @@ pub const InstallCompletionsCommand = struct { }, .zsh => { if (bun.getenvZ("fpath")) |fpath| { - var splitter = std.mem.split(u8, fpath, " "); + var splitter = std.mem.splitScalar(u8, fpath, ' '); while (splitter.next()) |dir| { completions_dir = dir; diff --git a/src/cli/outdated_command.zig b/src/cli/outdated_command.zig index af827fcbcbfba0..c15fc0ca4f4f74 100644 --- a/src/cli/outdated_command.zig +++ b/src/cli/outdated_command.zig @@ -427,14 +427,12 @@ pub const OutdatedCommand = struct { table.printColumnNames(); for (workspace_pkg_ids) |workspace_pkg_id| { - inline for ( - .{ - Behavior.prod, - Behavior.dev, - Behavior.peer, - Behavior.optional, - }, - ) |group_behavior| { + 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; diff --git a/src/cli/pack_command.zig b/src/cli/pack_command.zig index 7a89ca9fbba915..dc9db0f63a364d 100644 --- a/src/cli/pack_command.zig +++ b/src/cli/pack_command.zig @@ -15,7 +15,7 @@ const stringZ = bun.stringZ; const libarchive = @import("../libarchive/libarchive.zig").lib; const Archive = libarchive.Archive; const Expr = bun.js_parser.Expr; -const Semver = @import("../install/semver.zig"); +const Semver = bun.Semver; const File = bun.sys.File; const FD = bun.FD; const strings = bun.strings; @@ -1402,7 +1402,7 @@ pub const PackCommand = struct { if (comptime !for_publish) { if (manager.options.pack_destination.len == 0) { - Output.pretty("\n{}\n", .{fmtTarballFilename(package_name, package_version)}); + Output.pretty("\n{}\n", .{fmtTarballFilename(package_name, package_version, .normalize)}); } else { var dest_buf: PathBuffer = undefined; const abs_tarball_dest, _ = absTarballDestination( @@ -1726,7 +1726,6 @@ pub const PackCommand = struct { json.source, shasum, integrity, - abs_tarball_dest, ); printArchivedFilesAndPackages( @@ -1739,7 +1738,7 @@ pub const PackCommand = struct { if (comptime !for_publish) { if (manager.options.pack_destination.len == 0) { - Output.pretty("\n{}\n", .{fmtTarballFilename(package_name, package_version)}); + Output.pretty("\n{}\n", .{fmtTarballFilename(package_name, package_version, .normalize)}); } else { Output.pretty("\n{s}\n", .{abs_tarball_dest}); } @@ -1809,11 +1808,11 @@ pub const PackCommand = struct { ); const tarball_name = std.fmt.bufPrint(dest_buf[strings.withoutTrailingSlash(tarball_destination_dir).len..], "/{}\x00", .{ - fmtTarballFilename(package_name, package_version), + fmtTarballFilename(package_name, package_version, .normalize), }) catch { Output.errGeneric("archive destination name too long: \"{s}/{}\"", .{ strings.withoutTrailingSlash(tarball_destination_dir), - fmtTarballFilename(package_name, package_version), + fmtTarballFilename(package_name, package_version, .normalize), }); Global.crash(); }; @@ -1824,18 +1823,29 @@ pub const PackCommand = struct { }; } - fn fmtTarballFilename(package_name: string, package_version: string) TarballNameFormatter { + pub fn fmtTarballFilename(package_name: string, package_version: string, style: TarballNameFormatter.Style) TarballNameFormatter { return .{ .package_name = package_name, .package_version = package_version, + .style = style, }; } const TarballNameFormatter = struct { package_name: string, package_version: string, + style: Style, + + pub const Style = enum { + normalize, + raw, + }; pub fn format(this: TarballNameFormatter, comptime _: string, _: std.fmt.FormatOptions, writer: anytype) !void { + if (this.style == .raw) { + return writer.print("{s}-{s}.tgz", .{ this.package_name, this.package_version }); + } + if (this.package_name[0] == '@') { if (this.package_name.len > 1) { if (strings.indexOfChar(this.package_name, '/')) |slash| { diff --git a/src/cli/package_manager_command.zig b/src/cli/package_manager_command.zig index 09578a49624637..3fb40fc9dff894 100644 --- a/src/cli/package_manager_command.zig +++ b/src/cli/package_manager_command.zig @@ -17,7 +17,7 @@ const PackageManager = Install.PackageManager; const Lockfile = @import("../install/lockfile.zig"); const NodeModulesFolder = Lockfile.Tree.Iterator(.node_modules).Next; const Path = @import("../resolver/resolve_path.zig"); -const String = @import("../install/semver.zig").String; +const String = bun.Semver.String; const ArrayIdentityContext = bun.ArrayIdentityContext; const DepIdSet = std.ArrayHashMapUnmanaged(DependencyID, void, ArrayIdentityContext, false); const UntrustedCommand = @import("./pm_trusted_command.zig").UntrustedCommand; @@ -59,7 +59,7 @@ pub const PackageManagerCommand = struct { } pub fn printHash(ctx: Command.Context, file: File) !void { - @setCold(true); + @branchHint(.cold); const cli = try PackageManager.CommandLineArguments.parse(ctx.allocator, .pm); var pm, const cwd = try PackageManager.init(ctx, cli, PackageManager.Subcommand.pm); @@ -422,8 +422,7 @@ pub const PackageManagerCommand = struct { handleLoadLockfileErrors(load_lockfile, pm); const lockfile = load_lockfile.ok.lockfile; - const save_format = load_lockfile.saveFormat(pm); - lockfile.saveToDisk(save_format, pm.options.log_level.isVerbose()); + lockfile.saveToDisk(&load_lockfile, &pm.options); Global.exit(0); } diff --git a/src/cli/pm_trusted_command.zig b/src/cli/pm_trusted_command.zig index 5703a288ed1102..fb197f3071e1ea 100644 --- a/src/cli/pm_trusted_command.zig +++ b/src/cli/pm_trusted_command.zig @@ -7,7 +7,7 @@ const Command = @import("../cli.zig").Command; const Install = @import("../install/install.zig"); const LifecycleScriptSubprocess = Install.LifecycleScriptSubprocess; const PackageID = Install.PackageID; -const String = @import("../install/semver.zig").String; +const String = bun.Semver.String; const PackageManager = Install.PackageManager; const PackageManagerCommand = @import("./package_manager_command.zig").PackageManagerCommand; const Lockfile = Install.Lockfile; @@ -417,8 +417,7 @@ pub const TrustCommand = struct { try pm.lockfile.trusted_dependencies.?.put(ctx.allocator, @truncate(String.Builder.stringHash(name)), {}); } - const save_format = load_lockfile.saveFormat(pm); - pm.lockfile.saveToDisk(save_format, pm.options.log_level.isVerbose()); + pm.lockfile.saveToDisk(&load_lockfile, &pm.options); var buffer_writer = try bun.js_printer.BufferWriter.init(ctx.allocator); try buffer_writer.buffer.list.ensureTotalCapacity(ctx.allocator, package_json_contents.len + 1); diff --git a/src/cli/publish_command.zig b/src/cli/publish_command.zig index d1e26d06fcb176..43ff1eaabcf208 100644 --- a/src/cli/publish_command.zig +++ b/src/cli/publish_command.zig @@ -242,7 +242,6 @@ pub const PublishCommand = struct { json_source, shasum, integrity, - abs_tarball_path, ); Pack.Context.printSummary( @@ -876,7 +875,6 @@ pub const PublishCommand = struct { json_source: logger.Source, shasum: sha.SHA1.Digest, integrity: sha.SHA512.Digest, - abs_tarball_path: stringZ, ) OOM!string { bun.assertWithLocation(json.isObject(), @src()); @@ -928,10 +926,12 @@ pub const PublishCommand = struct { .value = Expr.init( E.String, .{ - .data = try bun.fmt.allocPrint(allocator, "http://{s}/{s}/-/{s}", .{ - strings.withoutTrailingSlash(registry.url.href), + .data = try bun.fmt.allocPrint(allocator, "http://{s}/{s}/-/{}", .{ + // always use replace https with http + // https://github.com/npm/cli/blob/9281ebf8e428d40450ad75ba61bc6f040b3bf896/workspaces/libnpmpublish/lib/publish.js#L120 + strings.withoutTrailingSlash(strings.withoutPrefixComptime(registry.url.href, "https://")), package_name, - std.fs.path.basename(abs_tarball_path), + Pack.fmtTarballFilename(package_name, package_version, .raw), }), }, logger.Loc.Empty, @@ -1362,8 +1362,8 @@ pub const PublishCommand = struct { // "_attachments" { - try writer.print(",\"_attachments\":{{\"{s}\":{{\"content_type\":\"{s}\",\"data\":\"", .{ - std.fs.path.basename(ctx.abs_tarball_path), + try writer.print(",\"_attachments\":{{\"{}\":{{\"content_type\":\"{s}\",\"data\":\"", .{ + Pack.fmtTarballFilename(ctx.package_name, ctx.package_version, .raw), "application/octet-stream", }); diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index a09dcb0e8f82d7..ec7ba403c8a67d 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -757,7 +757,7 @@ pub const RunCommand = struct { const dir_slice = target_path_buffer[0 .. prefix.len + len + dir_name.len]; if (Environment.isDebug) { - const dir_slice_u8 = std.unicode.utf16leToUtf8Alloc(bun.default_allocator, dir_slice) catch @panic("oom"); + const dir_slice_u8 = std.unicode.utf16LeToUtf8Alloc(bun.default_allocator, dir_slice) catch @panic("oom"); defer bun.default_allocator.free(dir_slice_u8); std.fs.deleteTreeAbsolute(dir_slice_u8) catch {}; std.fs.makeDirAbsolute(dir_slice_u8) catch @panic("huh?"); @@ -1262,9 +1262,9 @@ pub const RunCommand = struct { Output.flush(); } - fn _bootAndHandleError(ctx: Command.Context, path: string) bool { + fn _bootAndHandleError(ctx: Command.Context, path: string, loader: ?bun.options.Loader) bool { Global.configureAllocator(.{ .long_running = true }); - Run.boot(ctx, ctx.allocator.dupe(u8, path) catch return false) catch |err| { + Run.boot(ctx, ctx.allocator.dupe(u8, path) catch return false, loader) catch |err| { ctx.log.print(Output.errorWriter()) catch {}; Output.prettyErrorln("error: Failed to run {s} due to error {s}", .{ @@ -1348,7 +1348,7 @@ pub const RunCommand = struct { bun.CLI.Arguments.loadConfigPath(ctx.allocator, true, "bunfig.toml", ctx, .RunCommand) catch {}; } - _ = _bootAndHandleError(ctx, absolute_script_path.?); + _ = _bootAndHandleError(ctx, absolute_script_path.?, null); return true; } pub fn exec( @@ -1441,7 +1441,7 @@ pub const RunCommand = struct { @memcpy(entry_point_buf[cwd.len..][0..trigger.len], trigger); const entry_path = entry_point_buf[0 .. cwd.len + trigger.len]; - Run.boot(ctx, ctx.allocator.dupe(u8, entry_path) catch return false) catch |err| { + Run.boot(ctx, ctx.allocator.dupe(u8, entry_path) catch return false, null) catch |err| { ctx.log.print(Output.errorWriter()) catch {}; Output.prettyErrorln("error: Failed to run {s} due to error {s}", .{ @@ -1522,15 +1522,26 @@ pub const RunCommand = struct { // TODO: run module resolution here - try the next condition if the module can't be found log("Try resolve `{s}` in `{s}`", .{ target_name, this_transpiler.fs.top_level_dir }); - if (this_transpiler.resolver.resolve(this_transpiler.fs.top_level_dir, target_name, .entry_point_run)) |resolved| { - var resolved_mutable = resolved; - log("Resolved to: `{s}`", .{resolved_mutable.path().?.text}); - return _bootAndHandleError(ctx, resolved_mutable.path().?.text); - } else |_| if (this_transpiler.resolver.resolve(this_transpiler.fs.top_level_dir, try std.mem.join(ctx.allocator, "", &.{ "./", target_name }), .entry_point_run)) |resolved| { + if (this_transpiler.resolver.resolve(this_transpiler.fs.top_level_dir, target_name, .entry_point_run) catch + this_transpiler.resolver.resolve(this_transpiler.fs.top_level_dir, try std.mem.join(ctx.allocator, "", &.{ "./", target_name }), .entry_point_run)) |resolved| + { var resolved_mutable = resolved; - log("Resolved with `./` to: `{s}`", .{resolved_mutable.path().?.text}); - return _bootAndHandleError(ctx, resolved_mutable.path().?.text); - } else |_| {} + const path = resolved_mutable.path().?; + const loader: bun.options.Loader = this_transpiler.options.loaders.get(path.name.ext) orelse .tsx; + if (loader.canBeRunByBun() or loader == .html) { + log("Resolved to: `{s}`", .{path.text}); + return _bootAndHandleError(ctx, path.text, loader); + } else { + log("Resolved file `{s}` but ignoring because loader is {s}", .{ path.text, @tagName(loader) }); + } + } else |_| { + // Support globs for HTML entry points. + if (strings.hasSuffixComptime(target_name, ".html")) { + if (strings.containsChar(target_name, '*')) { + return _bootAndHandleError(ctx, target_name, .html); + } + } + } // execute a node_modules/.bin/ command, or (run only) a system command like 'ls' @@ -1565,7 +1576,7 @@ pub const RunCommand = struct { const PATH = this_transpiler.env.get("PATH") orelse ""; var path_for_which = PATH; - if (comptime bin_dirs_only) { + if (bin_dirs_only) { if (ORIGINAL_PATH.len < PATH.len) { path_for_which = PATH[0 .. PATH.len - (ORIGINAL_PATH.len + 1)]; } else { @@ -1594,7 +1605,7 @@ pub const RunCommand = struct { return true; } - if (comptime log_errors) { + if (log_errors) { const ext = std.fs.path.extension(target_name); const default_loader = options.defaultLoaders.get(ext); if (default_loader != null and default_loader.?.isJavaScriptLikeOrJSON() or target_name.len > 0 and (target_name[0] == '.' or target_name[0] == '/' or std.fs.path.isAbsolute(target_name))) { @@ -1619,7 +1630,7 @@ pub const RunCommand = struct { var entry_point_buf: [bun.MAX_PATH_BYTES + trigger.len]u8 = undefined; const cwd = try std.posix.getcwd(&entry_point_buf); @memcpy(entry_point_buf[cwd.len..][0..trigger.len], trigger); - try Run.boot(ctx, entry_point_buf[0 .. cwd.len + trigger.len]); + try Run.boot(ctx, entry_point_buf[0 .. cwd.len + trigger.len], null); return; } @@ -1649,7 +1660,7 @@ pub const RunCommand = struct { ); }; - Run.boot(ctx, normalized_filename) catch |err| { + Run.boot(ctx, normalized_filename, null) catch |err| { ctx.log.print(Output.errorWriter()) catch {}; Output.err(err, "Failed to run script \"{s}\"", .{std.fs.path.basename(normalized_filename)}); @@ -1724,7 +1735,7 @@ pub const BunXFastPath = struct { bun.reinterpretSlice(u8, &direct_launch_buffer), wpath, ) catch return; - Run.boot(ctx, utf8) catch |err| { + Run.boot(ctx, utf8, null) catch |err| { ctx.log.print(Output.errorWriter()) catch {}; Output.err(err, "Failed to run bin \"{s}\"", .{std.fs.path.basename(utf8)}); Global.exit(1); diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index d76218c15e77e7..244083f4a8d261 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -35,7 +35,6 @@ const Run = @import("../bun_js.zig").Run; var path_buf: bun.PathBuffer = undefined; var path_buf2: bun.PathBuffer = undefined; const PathString = bun.PathString; -const is_bindgen = false; const HTTPThread = bun.http.HTTPThread; const JSC = bun.JSC; @@ -84,7 +83,7 @@ fn escapeXml(str: string, writer: anytype) !void { try writer.writeAll(str[last..]); } } -fn fmtStatusTextLine(comptime status: @Type(.EnumLiteral), comptime emoji_or_color: bool) []const u8 { +fn fmtStatusTextLine(comptime status: @Type(.enum_literal), comptime emoji_or_color: bool) []const u8 { comptime { // emoji and color might be split into two different options in the future // some terminals support color, but not emoji. @@ -108,7 +107,7 @@ fn fmtStatusTextLine(comptime status: @Type(.EnumLiteral), comptime emoji_or_col } } -fn writeTestStatusLine(comptime status: @Type(.EnumLiteral), writer: anytype) void { +fn writeTestStatusLine(comptime status: @Type(.enum_literal), writer: anytype) void { if (Output.enable_ansi_colors_stderr) writer.print(fmtStatusTextLine(status, true), .{}) catch unreachable else @@ -272,9 +271,7 @@ pub const JunitReporter = struct { \\ ); - try this.contents.appendSlice(bun.default_allocator, - \\\n"); } @@ -1177,8 +1174,6 @@ pub const TestCommand = struct { }; pub fn exec(ctx: Command.Context) !void { - if (comptime is_bindgen) unreachable; - Output.is_github_action = Output.isGithubAction(); // print the version so you know its doing stuff if it takes a sec diff --git a/src/cli/upgrade_command.zig b/src/cli/upgrade_command.zig index 9c656a24c29e93..dc9204a14d0cbb 100644 --- a/src/cli/upgrade_command.zig +++ b/src/cli/upgrade_command.zig @@ -400,7 +400,7 @@ pub const UpgradeCommand = struct { }; pub fn exec(ctx: Command.Context) !void { - @setCold(true); + @branchHint(.cold); const args = bun.argv; if (args.len > 2) { diff --git a/src/codegen/bindgen.ts b/src/codegen/bindgen.ts index b3d8be92c67098..200dcf0caa6070 100644 --- a/src/codegen/bindgen.ts +++ b/src/codegen/bindgen.ts @@ -1485,7 +1485,7 @@ zigInternal.line("};"); zigInternal.line(); zigInternal.line("comptime {"); zigInternal.line(` if (bun.Environment.export_cpp_apis) {`); -zigInternal.line(" for (@typeInfo(binding_internals).Struct.decls) |decl| {"); +zigInternal.line(" for (@typeInfo(binding_internals).@\"struct\".decls) |decl| {"); zigInternal.line(" _ = &@field(binding_internals, decl.name);"); zigInternal.line(" }"); zigInternal.line(" }"); diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index acd608ed6cc4d5..8d8f01be847000 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -143,7 +143,7 @@ JSC_DEFINE_JIT_OPERATION(${DOMJITName( fnName, )}Wrapper, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); IGNORE_WARNINGS_BEGIN("frame-address") CallFrame* callFrame = DECLARE_CALL_FRAME(vm); IGNORE_WARNINGS_END @@ -378,7 +378,7 @@ export function generateHashTableComment(nameToUse, symbolName, obj, props = {}, externs += ` extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${protoSymbolName( obj.name, - name, + props[name], )}(void* ptr, JSC::JSGlobalObject*); namespace WebCore { static JSC::JSValue construct${symbolName(name)}PropertyCallback(JSC::VM &vm, JSC::JSObject* initialThisObject); @@ -967,7 +967,7 @@ function writeBarrier(symbolName, typeName, name, cacheName) { extern JSC_CALLCONV void ${symbolName(typeName, name)}SetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject *globalObject, JSC::EncodedJSValue value) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(thisValue)); thisObject->${cacheName}.set(vm, thisObject, JSValue::decode(value)); } @@ -998,7 +998,7 @@ function renderFieldsImpl( JSC_DEFINE_CUSTOM_GETTER(js${typeName}Constructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) { - VM& vm = JSC::getVM(lexicalGlobalObject); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); auto* globalObject = reinterpret_cast(lexicalGlobalObject); auto* prototype = jsDynamicCast<${prototypeName(typeName)}*>(JSValue::decode(thisValue)); @@ -1021,7 +1021,7 @@ JSC_DEFINE_CUSTOM_GETTER(js${typeName}Constructor, (JSGlobalObject * lexicalGlob ` JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); Zig::GlobalObject *globalObject = reinterpret_cast(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); @@ -1045,7 +1045,7 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObjec ` JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); @@ -1059,7 +1059,7 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObjec ` JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * globalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) { - auto& vm = globalObject->vm(); + auto& vm = JSC::getVM(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); if (UNLIKELY(!thisObject)) { @@ -1090,7 +1090,7 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObjec rows.push(` JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); Zig::GlobalObject *globalObject = reinterpret_cast(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); @@ -1106,7 +1106,7 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObjec rows.push(` JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, PropertyName attributeName)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); Zig::GlobalObject *globalObject = reinterpret_cast(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); @@ -1129,7 +1129,7 @@ JSC_DEFINE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap, (JSGlobalObjec ` JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsCast<${className(typeName)}*>(JSValue::decode(encodedThisValue)); JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); @@ -1146,7 +1146,7 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObjec ` JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue encodedThisValue, EncodedJSValue encodedValue, PropertyName attributeName)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = JSValue::decode(encodedThisValue); if (!thisValue.isObject()) { @@ -1166,7 +1166,7 @@ JSC_DEFINE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap, (JSGlobalObjec rows.push(` JSC_DEFINE_HOST_FUNCTION(${symbolName(typeName, name)}Callback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { - auto& vm = lexicalGlobalObject->vm(); + auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); ${className(typeName)}* thisObject = jsDynamicCast<${className(typeName)}*>(callFrame->thisValue()); @@ -2064,7 +2064,7 @@ const JavaScriptCoreBindings = struct { ` }; comptime { -${[...exports.values()].map(name => ` @export(JavaScriptCoreBindings.${name}, .{ .name = "${name}" });`).join("\n")} +${[...exports.values()].map(name => ` @export(&JavaScriptCoreBindings.${name}, .{ .name = "${name}" });`).join("\n")} }` ); } diff --git a/src/codegen/generate-js2native.ts b/src/codegen/generate-js2native.ts index 7034c0b9852b6a..8b2f46bbd0527b 100644 --- a/src/codegen/generate-js2native.ts +++ b/src/codegen/generate-js2native.ts @@ -236,7 +236,7 @@ export function getJS2NativeZig(gs2NativeZigPath: string) { .flatMap(x => { const base = basename(x.filename.replace(/\.bind\.ts$/, "")); return [ - ` @export(bun.gen.${base}.create${cap(x.symbol)}Callback, .{ .name = ${JSON.stringify( + ` @export(&bun.gen.${base}.create${cap(x.symbol)}Callback, .{ .name = ${JSON.stringify( `js2native_bindgen_${base}_${x.symbol}`, )} });`, ]; diff --git a/src/copy_file.zig b/src/copy_file.zig index 220aeb773395e3..d254711b49badc 100644 --- a/src/copy_file.zig +++ b/src/copy_file.zig @@ -60,7 +60,7 @@ const CopyFileReturnType = bun.sys.Maybe(void); pub fn copyFileWithState(in: InputType, out: InputType, copy_file_state: *CopyFileState) CopyFileReturnType { if (comptime Environment.isMac) { - const rc = posix.system.fcopyfile(in, out, null, posix.system.COPYFILE_DATA); + const rc = posix.system.fcopyfile(in, out, null, posix.system.COPYFILE{ .DATA = true }); switch (posix.errno(rc)) { .SUCCESS => return CopyFileReturnType.success, diff --git a/src/crash_handler.zig b/src/crash_handler.zig index 6a1ae522b207bc..982a2970a8abde 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -178,7 +178,7 @@ pub fn crashHandler( error_return_trace: ?*std.builtin.StackTrace, begin_addr: ?usize, ) noreturn { - @setCold(true); + @branchHint(.cold); if (bun.Environment.isDebug) bun.Output.disableScopedDebugWriter(); @@ -275,11 +275,11 @@ pub fn crashHandler( } else switch (bun.Environment.os) { .windows => { var name: std.os.windows.PWSTR = undefined; - const result = bun.windows.GetThreadDescription(std.os.windows.kernel32.GetCurrentThread(), &name); + const result = bun.windows.GetThreadDescription(bun.windows.GetCurrentThread(), &name); if (std.os.windows.HRESULT_CODE(result) == .SUCCESS and name[0] != 0) { writer.print("({})", .{bun.fmt.utf16(bun.span(name))}) catch std.posix.abort(); } else { - writer.print("(thread {d})", .{std.os.windows.kernel32.GetCurrentThreadId()}) catch std.posix.abort(); + writer.print("(thread {d})", .{bun.windows.GetCurrentThreadId()}) catch std.posix.abort(); } }, .mac, .linux => {}, @@ -301,7 +301,13 @@ pub fn crashHandler( var trace_buf: std.builtin.StackTrace = undefined; // If a trace was not provided, compute one now - const trace = error_return_trace orelse get_backtrace: { + const trace = @as(?*std.builtin.StackTrace, if (error_return_trace) |ert| + if (ert.index > 0) + ert + else + null + else + null) orelse get_backtrace: { trace_buf = std.builtin.StackTrace{ .index = 0, .instruction_addresses = &addr_buf, @@ -706,7 +712,7 @@ pub fn handleRootError(err: anyerror, error_return_trace: ?*std.builtin.StackTra } pub fn panicImpl(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, begin_addr: ?usize) noreturn { - @setCold(true); + @branchHint(.cold); crashHandler( if (bun.strings.eqlComptime(msg, "reached unreachable code")) .{ .@"unreachable" = {} } @@ -796,10 +802,10 @@ pub fn updatePosixSegfaultHandler(act: ?*std.posix.Sigaction) !void { } } - try std.posix.sigaction(std.posix.SIG.SEGV, act, null); - try std.posix.sigaction(std.posix.SIG.ILL, act, null); - try std.posix.sigaction(std.posix.SIG.BUS, act, null); - try std.posix.sigaction(std.posix.SIG.FPE, act, null); + std.posix.sigaction(std.posix.SIG.SEGV, act, null); + std.posix.sigaction(std.posix.SIG.ILL, act, null); + std.posix.sigaction(std.posix.SIG.BUS, act, null); + std.posix.sigaction(std.posix.SIG.FPE, act, null); } var windows_segfault_handle: ?windows.HANDLE = null; @@ -868,7 +874,7 @@ pub fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(windows ); } -extern "C" fn gnu_get_libc_version() ?[*:0]const u8; +extern "c" fn gnu_get_libc_version() ?[*:0]const u8; pub fn printMetadata(writer: anytype) !void { if (Output.enable_ansi_colors) { @@ -1146,19 +1152,19 @@ const StackLine = struct { fn callback(info: *std.posix.dl_phdr_info, _: usize, context: *CtxTy) !void { defer context.i += 1; - if (context.address < info.dlpi_addr) return; - const phdrs = info.dlpi_phdr[0..info.dlpi_phnum]; + if (context.address < info.addr) return; + const phdrs = info.phdr[0..info.phnum]; for (phdrs) |*phdr| { if (phdr.p_type != std.elf.PT_LOAD) continue; // Overflowing addition is used to handle the case of VSDOs // having a p_vaddr = 0xffffffffff700000 - const seg_start = info.dlpi_addr +% phdr.p_vaddr; + const seg_start = info.addr +% phdr.p_vaddr; const seg_end = seg_start + phdr.p_memsz; if (context.address >= seg_start and context.address < seg_end) { - // const name = bun.sliceTo(info.dlpi_name, 0) orelse ""; + // const name = bun.sliceTo(info.name, 0) orelse ""; context.result = .{ - .address = @intCast(context.address - info.dlpi_addr), + .address = @intCast(context.address - info.addr), .object = null, }; return error.Found; @@ -1470,7 +1476,7 @@ fn crash() noreturn { std.posix.SIG.HUP, std.posix.SIG.TERM, }) |sig| { - std.posix.sigaction(sig, &sigact, null) catch {}; + std.posix.sigaction(sig, &sigact, null); } @trap(); @@ -1481,7 +1487,7 @@ fn crash() noreturn { pub var verbose_error_trace = false; noinline fn coldHandleErrorReturnTrace(err_int_workaround_for_zig_ccall_bug: std.meta.Int(.unsigned, @bitSizeOf(anyerror)), trace: *std.builtin.StackTrace, comptime is_root: bool) void { - @setCold(true); + @branchHint(.cold); const err = @errorFromInt(err_int_workaround_for_zig_ccall_bug); // The format of the panic trace is slightly different in debug @@ -1582,9 +1588,7 @@ pub fn dumpStackTrace(trace: std.builtin.StackTrace) void { stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; break :attempt_dump; }; - var arena = bun.ArenaAllocator.init(bun.default_allocator); - defer arena.deinit(); - debug.writeStackTrace(trace, stderr, arena.allocator(), debug_info, std.io.tty.detectConfig(std.io.getStdErr())) catch |err| { + debug.writeStackTrace(trace, stderr, debug_info, std.io.tty.detectConfig(std.io.getStdErr())) catch |err| { stderr.print("Unable to dump stack trace: {s}\nFallback trace:\n", .{@errorName(err)}) catch return; break :attempt_dump; }; diff --git a/src/css/build-prefixes.js b/src/css/build-prefixes.js index bb36e786692b95..bd799194c2788d 100644 --- a/src/css/build-prefixes.js +++ b/src/css/build-prefixes.js @@ -520,16 +520,26 @@ let browsersZig = `pub const Browsers = struct { ${allBrowsers.join(": ?u32 = null,\n")}: ?u32 = null, pub usingnamespace BrowsersImpl(@This()); }`; +let field_len = 0; let flagsZig = `pub const Features = packed struct(u32) { ${flags .map((flag, i) => { if (Array.isArray(flag)) { // return `const ${flag[0]} = ${flag[1].map(f => `Self::${f}.bits()`).join(" | ")};`; - return `const ${flag[0]} = Features.fromNames(${flag[1].map(f => `"${f}"`).join(", ")});`; + return `pub const ${flag[0]} = Features.fromNames(&.{${flag[1].map(f => `"${f}"`).join(", ")}});`; } else { - return `${flag}: bool = 1 << ${i},`; + field_len++; + return `${flag}: bool = false,`; } }) + .concat(`__unused: u${32 - field_len} = 0,`) + .sort((a, b) => { + const a_is_const = a.startsWith("const"); + const b_is_const = b.startsWith("const"); + if (a_is_const && !b_is_const) return 1; + if (!a_is_const && b_is_const) return -1; + return 0; + }) .join("\n ")} pub usingnamespace css.Bitflags(@This()); @@ -593,7 +603,7 @@ pub const Feature = enum { pub fn prefixesFor(this: *const Feature, browsers: Browsers) VendorPrefix { var prefixes = VendorPrefix{ .none = true }; - switch (this.*) { + switch (this) { ${[...p] .map(([features, versions]) => { return `${features.map(name => `.${enumify(name)}`).join(" ,\n ")} => { @@ -673,7 +683,7 @@ const Browsers = @import("./targets.zig").Browsers; pub const Feature = enum { ${[...compat.keys()].flat().map(enumify).sort().join(",\n ")}, - pub fn isCompatible(this: *const Feature, browsers: Browsers) bool { + pub fn isCompatible(this: Feature, browsers: Browsers) bool { switch (this.*) { ${[...compat] .map( diff --git a/src/css/compat.zig b/src/css/compat.zig index 7d94f023d8c464..3dad0d4067efec 100644 --- a/src/css/compat.zig +++ b/src/css/compat.zig @@ -441,7 +441,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -533,7 +533,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -578,7 +578,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -623,7 +623,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -668,7 +668,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -713,7 +713,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -758,7 +758,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -803,7 +803,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -895,7 +895,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -940,7 +940,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1004,23 +1004,13 @@ pub const Feature = enum { return false; } } - if (browsers.safari) |version| { - if (version < 721152) { - return false; - } - } if (browsers.opera) |version| { if (version < 4718592) { return false; } } - if (browsers.ios_saf) |version| { - if (version < 721664) { - return false; - } - } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1029,7 +1019,7 @@ pub const Feature = enum { return false; } } - if (browsers.ie != null) { + if (browsers.ie != null or browsers.ios_saf != null or browsers.safari != null) { return false; } }, @@ -1065,7 +1055,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1155,7 +1145,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1200,7 +1190,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1250,7 +1240,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1337,7 +1327,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1382,7 +1372,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1427,7 +1417,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1467,7 +1457,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1512,7 +1502,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1557,7 +1547,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } @@ -1617,7 +1607,7 @@ pub const Feature = enum { } } if (browsers.android) |version| { - if (version < 8323072) { + if (version < 8585216) { return false; } } diff --git a/src/css/context.zig b/src/css/context.zig index 09c9e59373c206..7a76deafbaedc0 100644 --- a/src/css/context.zig +++ b/src/css/context.zig @@ -81,6 +81,10 @@ pub const PropertyHandlerContext = struct { }; } + pub fn addDarkRule(this: *@This(), allocator: Allocator, property: css.Property) void { + this.dark.append(allocator, property) catch bun.outOfMemory(); + } + pub fn addLogicalRule(this: *@This(), allocator: Allocator, ltr: css.Property, rtl: css.Property) void { this.ltr.append(allocator, ltr) catch unreachable; this.rtl.append(allocator, rtl) catch unreachable; @@ -171,7 +175,7 @@ pub const PropertyHandlerContext = struct { .feature = MediaFeature{ .plain = .{ .name = .{ .standard = MediaFeatureId.@"prefers-color-scheme" }, - .value = .{ .ident = .{ .v = "dark " } }, + .value = .{ .ident = .{ .v = "dark" } }, }, }, }, diff --git a/src/css/css_parser.zig b/src/css/css_parser.zig index a73ff1d3fef7b2..17a20262d6879c 100644 --- a/src/css/css_parser.zig +++ b/src/css/css_parser.zig @@ -243,6 +243,7 @@ pub const Location = css_rules.Location; pub const Error = Err(ParserError); pub fn Result(comptime T: type) type { + @setEvalBranchQuota(1_000_000); return Maybe(T, ParseError(ParserError)); } @@ -271,11 +272,11 @@ pub fn DefineListShorthand(comptime T: type) type { return struct {}; } -pub fn DefineShorthand(comptime T: type, comptime property_name: PropertyIdTag) type { +pub fn DefineShorthand(comptime T: type, comptime property_name: PropertyIdTag, comptime PropertyFieldMap: anytype) type { _ = property_name; // autofix // TODO: validate map, make sure each field is set // make sure each field is same index as in T - _ = T.PropertyFieldMap; + _ = PropertyFieldMap; return struct { /// Returns a shorthand from the longhand properties defined in the given declaration block. @@ -527,9 +528,9 @@ pub fn DefineSizeShorthand(comptime T: type, comptime V: type) type { pub fn DeriveParse(comptime T: type) type { const tyinfo = @typeInfo(T); - const is_union_enum = tyinfo == .Union; - const enum_type = if (comptime is_union_enum) @typeInfo(tyinfo.Union.tag_type.?) else tyinfo; - const enum_actual_type = if (comptime is_union_enum) tyinfo.Union.tag_type.? else T; + const is_union_enum = tyinfo == .@"union"; + const enum_type = if (comptime is_union_enum) @typeInfo(tyinfo.@"union".tag_type.?) else tyinfo; + const enum_actual_type = if (comptime is_union_enum) tyinfo.@"union".tag_type.? else T; const Map = bun.ComptimeEnumMap(enum_actual_type); @@ -541,7 +542,7 @@ pub fn DeriveParse(comptime T: type) type { var first_payload_index: ?usize = null; var payload_count: usize = 0; var void_count: usize = 0; - for (tyinfo.Union.fields, 0..) |field, i| { + for (tyinfo.@"union".fields, 0..) |field, i| { if (field.type == void) { void_count += 1; if (first_void_index == null) first_void_index = i; @@ -619,7 +620,7 @@ pub fn DeriveParse(comptime T: type) type { ) Result(T) { const last_payload_index = first_payload_index + payload_count - 1; if (comptime maybe_first_void_index == null) { - inline for (tyinfo.Union.fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { + inline for (tyinfo.@"union".fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { if (comptime (i == last_payload_index)) { return .{ .result = switch (generic.parseFor(field.type)(input)) { .result => |v| @unionInit(T, field.name, v), @@ -637,7 +638,7 @@ pub fn DeriveParse(comptime T: type) type { const void_fields = bun.meta.EnumFields(T)[first_void_index .. first_void_index + void_count]; if (comptime void_count == 1) { - const void_field = enum_type.Enum.fields[first_void_index]; + const void_field = enum_type.@"enum".fields[first_void_index]; // The field is declared before the payload fields. // So try to parse an ident matching the name of the field, then fallthrough // to parsing the payload fields. @@ -647,7 +648,7 @@ pub fn DeriveParse(comptime T: type) type { return .{ .result = @enumFromInt(void_field.value) }; } - inline for (tyinfo.Union.fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { + inline for (tyinfo.@"union".fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { if (comptime (i == last_payload_index and last_payload_index > first_void_index)) { return .{ .result = switch (generic.parseFor(field.type)(input)) { .result => |v| @unionInit(T, field.name, v), @@ -659,7 +660,7 @@ pub fn DeriveParse(comptime T: type) type { } } } else { - inline for (tyinfo.Union.fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { + inline for (tyinfo.@"union".fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { if (comptime (i == last_payload_index and last_payload_index > first_void_index)) { return .{ .result = switch (generic.parseFor(field.type)(input)) { .result => |v| @unionInit(T, field.name, v), @@ -692,7 +693,7 @@ pub fn DeriveParse(comptime T: type) type { input.reset(&state); } - inline for (tyinfo.Union.fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { + inline for (tyinfo.@"union".fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { if (comptime (i == last_payload_index and last_payload_index > first_void_index)) { return .{ .result = switch (generic.parseFor(field.type)(input)) { .result => |v| @unionInit(T, field.name, v), @@ -704,7 +705,7 @@ pub fn DeriveParse(comptime T: type) type { } } } else if (comptime first_void_index > first_payload_index) { - inline for (tyinfo.Union.fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { + inline for (tyinfo.@"union".fields[first_payload_index .. first_payload_index + payload_count], first_payload_index..) |field, i| { if (comptime (i == last_payload_index and last_payload_index > first_void_index)) { return .{ .result = switch (generic.parseFor(field.type)(input)) { .result => |v| @unionInit(T, field.name, v), @@ -742,7 +743,7 @@ pub fn DeriveParse(comptime T: type) type { // comptime payload_count: usize, // ) Result(T) { // const last_payload_index = first_payload_index + payload_count - 1; - // inline for (tyinfo.Union.fields[first_payload_index..], first_payload_index..) |field, i| { + // inline for (tyinfo.@"union".fields[first_payload_index..], first_payload_index..) |field, i| { // if (comptime (i == last_payload_index and last_payload_index > first_void_index)) { // return generic.parseFor(field.type)(input); // } @@ -773,24 +774,24 @@ pub fn DeriveParse(comptime T: type) type { pub fn DeriveToCss(comptime T: type) type { const tyinfo = @typeInfo(T); const enum_fields = bun.meta.EnumFields(T); - const is_enum_or_union_enum = tyinfo == .Union or tyinfo == .Enum; + const is_enum_or_union_enum = tyinfo == .@"union" or tyinfo == .@"enum"; return struct { pub fn toCss(this: *const T, comptime W: type, dest: *Printer(W)) PrintErr!void { if (comptime is_enum_or_union_enum) { inline for (std.meta.fields(T), 0..) |field, i| { if (@intFromEnum(this.*) == enum_fields[i].value) { - if (comptime field.type == void) { + if (comptime tyinfo == .@"enum" or field.type == void) { return dest.writeStr(enum_fields[i].name); } else if (comptime generic.hasToCss(field.type)) { return generic.toCss(field.type, &@field(this, field.name), W, dest); - } else if (@hasDecl(field.type, "__generateToCss") and @typeInfo(field.type) == .Struct) { + } else if (@hasDecl(field.type, "__generateToCss") and @typeInfo(field.type) == .@"struct") { const variant_fields = std.meta.fields(field.type); if (variant_fields.len > 1) { const last = variant_fields.len - 1; inline for (variant_fields, 0..) |variant_field, j| { // Unwrap it from the optional - if (@typeInfo(variant_field.type) == .Optional) { + if (@typeInfo(variant_field.type) == .optional) { if (@field(@field(this, field.name), variant_field.name)) |*value| { try value.toCss(W, dest); } @@ -899,10 +900,7 @@ pub fn DefineEnumProperty(comptime T: type) type { }; } -pub fn DeriveValueType(comptime T: type) type { - _ = @typeInfo(T).Enum; - - const ValueTypeMap = T.ValueTypeMap; +pub fn DeriveValueType(comptime T: type, comptime ValueTypeMap: anytype) type { const field_values: []const MediaFeatureType = field_values: { const fields = std.meta.fields(T); var mapping: [fields.len]MediaFeatureType = undefined; @@ -927,7 +925,7 @@ pub fn DeriveValueType(comptime T: type) type { } fn consume_until_end_of_block(block_type: BlockType, tokenizer: *Tokenizer) void { - @setCold(true); + @branchHint(.cold); var stack = SmallList(BlockType, 16){}; stack.appendAssumeCapacity(block_type); @@ -3812,6 +3810,18 @@ pub const Parser = struct { } } + pub fn expectSquareBracketBlock(this: *Parser) Result(void) { + const start_location = this.currentSourceLocation(); + const tok = switch (this.next()) { + .err => |e| return .{ .err = e }, + .result => |v| v, + }; + switch (tok.*) { + .open_square => return .{ .result = {} }, + else => return .{ .err = start_location.newUnexpectedTokenError(tok.*) }, + } + } + /// Parse a and return the unescaped value. pub fn expectUrl(this: *Parser) Result([]const u8) { const start_location = this.currentSourceLocation(); @@ -4074,7 +4084,7 @@ pub const Delimiters = packed struct(u8) { const NONE: Delimiters = .{}; - pub fn getDelimiter(comptime tag: @TypeOf(.EnumLiteral)) Delimiters { + pub fn getDelimiter(comptime tag: @TypeOf(.enum_literal)) Delimiters { var empty = Delimiters{}; @field(empty, @tagName(tag)) = true; return empty; @@ -4428,7 +4438,7 @@ const Tokenizer = struct { // Any other valid case here already resulted in IDHash. '0'...'9', '-' => true, else => false, - }) break :brk .{ .hash = this.consumeName() }; + }) break :brk .{ .unrestrictedhash = this.consumeName() }; break :brk .{ .delim = '#' }; }, '$' => brk: { @@ -5000,7 +5010,7 @@ const Tokenizer = struct { // todo_stuff.match_byte switch (this.nextByteUnchecked()) { ' ', '\t', '\n', '\r', FORM_FEED_BYTE => { - var value = .{ .borrowed = this.sliceFrom(start_pos) }; + var value: CopyOnWriteStr = .{ .borrowed = this.sliceFrom(start_pos) }; return this.consumeUrlEnd(start_pos, &value); }, ')' => { @@ -5463,7 +5473,7 @@ const TokenKind = enum { /// A [``](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "unrestricted" /// /// The value does not include the `#` marker. - hash, + unrestrictedhash, /// A [``](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "id" /// @@ -5587,7 +5597,7 @@ pub const Token = union(TokenKind) { /// A [``](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "unrestricted" /// /// The value does not include the `#` marker. - hash: []const u8, + unrestrictedhash: []const u8, /// A [``](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "id" /// @@ -5706,7 +5716,7 @@ pub const Token = union(TokenKind) { inline .ident, .function, .at_keyword, - .hash, + .unrestrictedhash, .idhash, .quoted_string, .bad_string, @@ -5753,13 +5763,9 @@ pub const Token = union(TokenKind) { try writer.writeAll("@"); try serializer.serializeIdentifier(this.at_keyword, writer); }, - .hash => { - try writer.writeAll("#"); - try serializer.serializeName(this.hash, writer); - }, - .idhash => { + .unrestrictedhash, .idhash => |v| { try writer.writeAll("#"); - try serializer.serializeName(this.idhash, writer); + try serializer.serializeName(v, writer); }, .quoted_string => |x| { try serializer.serializeName(x, writer); @@ -5852,7 +5858,7 @@ pub const Token = union(TokenKind) { try dest.writeStr("@"); return serializer.serializeIdentifier(value, dest) catch return dest.addFmtError(); }, - .hash => |value| { + .unrestrictedhash => |value| { try dest.writeStr("#"); return serializer.serializeName(value, dest) catch return dest.addFmtError(); }, @@ -6393,23 +6399,10 @@ pub const serializer = struct { }; } else notation: { var buf: [129]u8 = undefined; - // We must pass finite numbers to dtoa_short - if (std.math.isPositiveInf(value)) { - const output = "1e999"; - try writer.writeAll(output); - return; - } else if (std.math.isNegativeInf(value)) { - const output = "-1e999"; - try writer.writeAll(output); - return; - } - // We shouldn't receive NaN here. - // NaN is not a valid CSS token and any inlined calculations from `calc()` we ensure - // are not NaN. - bun.debugAssert(!std.math.isNan(value)); - const str, const notation = dtoa_short(&buf, value, 6); + const str, const maybe_notaton = try dtoa_short(&buf, value, 6); try writer.writeAll(str); - break :notation notation; + if (maybe_notaton) |notation| break :notation notation; + return; }; if (int_value == null and fract(value) == 0) { @@ -6480,215 +6473,9 @@ pub const serializer = struct { } }; -pub inline fn implementDeepClone(comptime T: type, this: *const T, allocator: Allocator) T { - const tyinfo = @typeInfo(T); - - if (comptime bun.meta.isSimpleCopyType(T)) { - return this.*; - } - - if (comptime bun.meta.looksLikeListContainerType(T)) |result| { - return switch (result) { - .array_list => deepClone(result.child, allocator, this), - .baby_list => @panic("Not implemented."), - .small_list => this.deepClone(allocator), - }; - } - - if (comptime T == []const u8) { - return this.*; - } - - if (comptime @typeInfo(T) == .Pointer) { - const TT = std.meta.Child(T); - return implementEql(TT, this.*); - } - - return switch (tyinfo) { - .Struct => { - var strct: T = undefined; - inline for (tyinfo.Struct.fields) |field| { - if (comptime generic.canTransitivelyImplementDeepClone(field.type) and @hasDecl(field.type, "__generateDeepClone")) { - @field(strct, field.name) = implementDeepClone(field.type, &field(this, field.name, allocator)); - } else { - @field(strct, field.name) = generic.deepClone(field.type, &@field(this, field.name), allocator); - } - } - return strct; - }, - .Union => { - inline for (bun.meta.EnumFields(T), tyinfo.Union.fields) |enum_field, union_field| { - if (@intFromEnum(this.*) == enum_field.value) { - if (comptime generic.canTransitivelyImplementDeepClone(union_field.type) and @hasDecl(union_field.type, "__generateDeepClone")) { - return @unionInit(T, enum_field.name, implementDeepClone(union_field.type, &@field(this, enum_field.name), allocator)); - } - return @unionInit(T, enum_field.name, generic.deepClone(union_field.type, &@field(this, enum_field.name), allocator)); - } - } - unreachable; - }, - else => @compileError("Unhandled type " ++ @typeName(T)), - }; -} - -/// A function to implement `lhs.eql(&rhs)` for the many types in the CSS parser that needs this. -/// -/// This is the equivalent of doing `#[derive(PartialEq])` in Rust. -/// -/// This function only works on simple types like: -/// - Simple equality types (e.g. integers, floats, strings, enums, etc.) -/// - Types which implement a `.eql(lhs: *const @This(), rhs: *const @This()) bool` function -/// -/// Or compound types composed of simple types such as: -/// - Pointers to simple types -/// - Optional simple types -/// - Structs, Arrays, and Unions -pub fn implementEql(comptime T: type, this: *const T, other: *const T) bool { - const tyinfo = @typeInfo(T); - if (comptime bun.meta.isSimpleEqlType(T)) { - return this.* == other.*; - } - if (comptime T == []const u8) { - return bun.strings.eql(this.*, other.*); - } - if (comptime @typeInfo(T) == .Pointer) { - const TT = std.meta.Child(T); - return implementEql(TT, this.*, other.*); - } - if (comptime @typeInfo(T) == .Optional) { - const TT = std.meta.Child(T); - if (this.* != null and other.* != null) return implementEql(TT, &this.*.?, &other.*.?); - return false; - } - return switch (tyinfo) { - .Optional => @compileError("Handled above, this means Zack wrote a bug."), - .Pointer => @compileError("Handled above, this means Zack wrote a bug."), - .Array => { - const Child = std.meta.Child(T); - if (comptime bun.meta.isSimpleEqlType(Child)) { - return std.mem.eql(Child, &this.*, &other.*); - } - if (this.len != other.len) return false; - if (comptime generic.canTransitivelyImplementEql(Child) and @hasDecl(Child, "__generateEql")) { - for (this.*, other.*) |*a, *b| { - if (!implementEql(Child, &a, &b)) return false; - } - } else { - for (this.*, other.*) |*a, *b| { - if (!generic.eql(Child, a, b)) return false; - } - } - return true; - }, - .Struct => { - inline for (tyinfo.Struct.fields) |field| { - if (!generic.eql(field.type, &@field(this, field.name), &@field(other, field.name))) return false; - } - return true; - }, - .Union => { - if (tyinfo.Union.tag_type == null) @compileError("Unions must have a tag type"); - if (@intFromEnum(this.*) != @intFromEnum(other.*)) return false; - const enum_fields = bun.meta.EnumFields(T); - inline for (enum_fields, std.meta.fields(T)) |enum_field, union_field| { - if (enum_field.value == @intFromEnum(this.*)) { - if (union_field.type != void) { - if (comptime generic.canTransitivelyImplementEql(union_field.type) and @hasDecl(union_field.type, "__generateEql")) { - return implementEql(union_field.type, &@field(this, enum_field.name), &@field(other, enum_field.name)); - } - return generic.eql(union_field.type, &@field(this, enum_field.name), &@field(other, enum_field.name)); - } else { - return true; - } - } - } - unreachable; - }, - else => @compileError("Unsupported type: " ++ @typeName(T)), - }; -} - -pub fn implementHash(comptime T: type, this: *const T, hasher: *std.hash.Wyhash) void { - const tyinfo = @typeInfo(T); - if (comptime T == void) return; - if (comptime bun.meta.isSimpleEqlType(T)) { - return hasher.update(std.mem.asBytes(&this)); - } - if (comptime bun.meta.looksLikeListContainerType(T)) |result| { - const list = switch (result) { - .array_list => this.items[0..], - .baby_list => this.sliceConst(), - .small_list => this.slice(), - }; - bun.writeAnyToHasher(hasher, list.len); - for (list) |*item| { - generic.hash(tyinfo.Array.child, item, hasher); - } - return; - } - if (comptime T == []const u8) { - return hasher.update(this.*); - } - if (comptime @typeInfo(T) == .Pointer) { - @compileError("Invalid type for implementHash(): " ++ @typeName(T)); - } - if (comptime @typeInfo(T) == .Optional) { - @compileError("Invalid type for implementHash(): " ++ @typeName(T)); - } - return switch (tyinfo) { - .Optional => { - if (this.* == null) { - bun.writeAnyToHasher(hasher, "null"); - } else { - bun.writeAnyToHasher(hasher, "some"); - generic.hash(tyinfo.Optional.child, &this.*.?, hasher); - } - }, - .Pointer => { - generic.hash(tyinfo.Pointer.child, &this.*, hasher); - }, - .Array => { - bun.writeAnyToHasher(hasher, this.len); - for (this.*[0..]) |*item| { - generic.hash(tyinfo.Array.child, item, hasher); - } - }, - .Struct => { - inline for (tyinfo.Struct.fields) |field| { - if (comptime generic.hasHash(field.type)) { - generic.hash(field.type, &@field(this, field.name), hasher); - } else if (@hasDecl(field.type, "__generateHash") and @typeInfo(field.type) == .Struct) { - implementHash(field.type, &@field(this, field.name), hasher); - } else { - @compileError("Can't hash these fields: " ++ @typeName(field.type) ++ ". On " ++ @typeName(T)); - } - } - return; - }, - .Enum => { - bun.writeAnyToHasher(hasher, @intFromEnum(this.*)); - }, - .Union => { - if (tyinfo.Union.tag_type == null) @compileError("Unions must have a tag type"); - bun.writeAnyToHasher(hasher, @intFromEnum(this.*)); - const enum_fields = bun.meta.EnumFields(T); - inline for (enum_fields, std.meta.fields(T)) |enum_field, union_field| { - if (enum_field.value == @intFromEnum(this.*)) { - const field = union_field; - if (comptime generic.hasHash(field.type)) { - generic.hash(field.type, &@field(this, field.name), hasher); - } else if (@hasDecl(field.type, "__generateHash") and @typeInfo(field.type) == .Struct) { - implementHash(field.type, &@field(this, field.name), hasher); - } else { - @compileError("Can't hash these fields: " ++ @typeName(field.type) ++ ". On " ++ @typeName(T)); - } - } - } - return; - }, - else => @compileError("Unsupported type: " ++ @typeName(T)), - }; -} +pub const implementEql = generic.implementEql; +pub const implementHash = generic.implementHash; +pub const implementDeepClone = generic.implementDeepClone; pub const parse_utility = struct { /// Parse a value from a string. @@ -6772,12 +6559,9 @@ pub const to_css = struct { } pub fn float32(this: f32, writer: anytype) !void { - var scratch: [64]u8 = undefined; - // PERF/TODO: Compare this to Rust dtoa-short crate - const floats = std.fmt.formatFloat(scratch[0..], this, .{ - .mode = .decimal, - }) catch unreachable; - return writer.writeAll(floats); + var scratch: [129]u8 = undefined; + const str, _ = try dtoa_short(&scratch, this, 6); + return writer.writeAll(str); } fn maxDigits(comptime T: type) usize { @@ -6869,7 +6653,27 @@ const Notation = struct { } }; -pub fn dtoa_short(buf: *[129]u8, value: f32, comptime precision: u8) struct { []u8, Notation } { +/// Writes float with precision. +/// +/// Returns null if value was an infinite number +pub fn dtoa_short(buf: *[129]u8, value: f32, comptime precision: u8) !struct { []u8, ?Notation } { + // We must pass finite numbers to dtoa_short_impl + if (std.math.isPositiveInf(value)) { + buf[0.."1e999".len].* = "1e999".*; + return .{ buf[0.."1e999".len], null }; + } else if (std.math.isNegativeInf(value)) { + buf[0.."-1e999".len].* = "-1e999".*; + return .{ buf[0.."-1e999".len], null }; + } + // We shouldn't receive NaN here. + // NaN is not a valid CSS token and any inlined calculations from `calc()` we ensure + // are not NaN. + bun.debugAssert(!std.math.isNan(value)); + const str, const notation = dtoa_short_impl(buf, value, precision); + return .{ str, notation }; +} + +pub fn dtoa_short_impl(buf: *[129]u8, value: f32, comptime precision: u8) struct { []u8, Notation } { buf[0] = '0'; bun.debugAssert(std.math.isFinite(value)); const buf_len = bun.fmt.FormatDouble.dtoa(@ptrCast(buf[1..].ptr), @floatCast(value)).len; diff --git a/src/css/declaration.zig b/src/css/declaration.zig index 2ce5b57cf9224a..c2bb443209248b 100644 --- a/src/css/declaration.zig +++ b/src/css/declaration.zig @@ -24,6 +24,12 @@ const FontHandler = css.css_properties.font.FontHandler; const InsetHandler = css.css_properties.margin_padding.InsetHandler; const SizeHandler = css.css_properties.size.SizeHandler; const FlexHandler = css.css_properties.flex.FlexHandler; +const AlignHandler = css.css_properties.@"align".AlignHandler; +const TransitionHandler = css.css_properties.transition.TransitionHandler; +const TransformHandler = css.css_properties.transform.TransformHandler; +const ColorSchemeHandler = css.css_properties.ui.ColorSchemeHandler; +const BoxShadowHandler = css.css_properties.box_shadow.BoxShadowHandler; +// const GridHandler = css.css_properties.g /// A CSS declaration block. /// @@ -334,12 +340,17 @@ pub const DeclarationHandler = struct { background: BackgroundHandler = .{}, border: BorderHandler = .{}, flex: FlexHandler = .{}, + @"align": AlignHandler = .{}, size: SizeHandler = .{}, margin: MarginHandler = .{}, padding: PaddingHandler = .{}, scroll_margin: ScrollMarginHandler = .{}, + transition: TransitionHandler = .{}, font: FontHandler = .{}, inset: InsetHandler = .{}, + transform: TransformHandler = .{}, + box_shadow: BoxShadowHandler = .{}, + color_scheme: ColorSchemeHandler = .{}, fallback: FallbackHandler = .{}, direction: ?css.css_properties.text.Direction, decls: DeclarationList, @@ -359,12 +370,17 @@ pub const DeclarationHandler = struct { this.background.finalize(&this.decls, context); this.border.finalize(&this.decls, context); this.flex.finalize(&this.decls, context); + this.@"align".finalize(&this.decls, context); this.size.finalize(&this.decls, context); this.margin.finalize(&this.decls, context); this.padding.finalize(&this.decls, context); this.scroll_margin.finalize(&this.decls, context); + this.transition.finalize(&this.decls, context); this.font.finalize(&this.decls, context); this.inset.finalize(&this.decls, context); + this.transform.finalize(&this.decls, context); + this.box_shadow.finalize(&this.decls, context); + this.color_scheme.finalize(&this.decls, context); this.fallback.finalize(&this.decls, context); } @@ -373,12 +389,17 @@ pub const DeclarationHandler = struct { return this.background.handleProperty(property, &this.decls, context) or this.border.handleProperty(property, &this.decls, context) or this.flex.handleProperty(property, &this.decls, context) or + this.@"align".handleProperty(property, &this.decls, context) or this.size.handleProperty(property, &this.decls, context) or this.margin.handleProperty(property, &this.decls, context) or this.padding.handleProperty(property, &this.decls, context) or this.scroll_margin.handleProperty(property, &this.decls, context) or + this.transition.handleProperty(property, &this.decls, context) or this.font.handleProperty(property, &this.decls, context) or this.inset.handleProperty(property, &this.decls, context) or + this.transform.handleProperty(property, &this.decls, context) or + this.box_shadow.handleProperty(property, &this.decls, context) or + this.color_scheme.handleProperty(property, &this.decls, context) or this.fallback.handleProperty(property, &this.decls, context); } diff --git a/src/css/generics.zig b/src/css/generics.zig index 8d90ca52878869..9c7fbb3a230b81 100644 --- a/src/css/generics.zig +++ b/src/css/generics.zig @@ -24,6 +24,220 @@ const DashedIdent = css.DashedIdent; const DashedIdentFns = css.DashedIdentFns; const Ident = css.Ident; const IdentFns = css.IdentFns; +const VendorPrefix = css.VendorPrefix; + +pub inline fn implementDeepClone(comptime T: type, this: *const T, allocator: Allocator) T { + const tyinfo = @typeInfo(T); + + if (comptime bun.meta.isSimpleCopyType(T)) { + return this.*; + } + + if (comptime bun.meta.looksLikeListContainerType(T)) |result| { + return switch (result) { + .array_list => deepClone(result.child, allocator, this), + .baby_list => @panic("Not implemented."), + .small_list => this.deepClone(allocator), + }; + } + + if (comptime T == []const u8) { + return this.*; + } + + if (comptime @typeInfo(T) == .pointer) { + const TT = std.meta.Child(T); + return implementEql(TT, this.*); + } + + return switch (tyinfo) { + .@"struct" => { + var strct: T = undefined; + inline for (tyinfo.@"struct".fields) |field| { + if (comptime canTransitivelyImplementDeepClone(field.type) and @hasDecl(field.type, "__generateDeepClone")) { + @field(strct, field.name) = implementDeepClone(field.type, &field(this, field.name, allocator)); + } else { + @field(strct, field.name) = deepClone(field.type, &@field(this, field.name), allocator); + } + } + return strct; + }, + .@"union" => { + inline for (bun.meta.EnumFields(T), tyinfo.@"union".fields) |enum_field, union_field| { + if (@intFromEnum(this.*) == enum_field.value) { + if (comptime canTransitivelyImplementDeepClone(union_field.type) and @hasDecl(union_field.type, "__generateDeepClone")) { + return @unionInit(T, enum_field.name, implementDeepClone(union_field.type, &@field(this, enum_field.name), allocator)); + } + return @unionInit(T, enum_field.name, deepClone(union_field.type, &@field(this, enum_field.name), allocator)); + } + } + unreachable; + }, + else => @compileError("Unhandled type " ++ @typeName(T)), + }; +} + +/// A function to implement `lhs.eql(&rhs)` for the many types in the CSS parser that needs this. +/// +/// This is the equivalent of doing `#[derive(PartialEq])` in Rust. +/// +/// This function only works on simple types like: +/// - Simple equality types (e.g. integers, floats, strings, enums, etc.) +/// - Types which implement a `.eql(lhs: *const @This(), rhs: *const @This()) bool` function +/// +/// Or compound types composed of simple types such as: +/// - Pointers to simple types +/// - Optional simple types +/// - Structs, Arrays, and Unions +pub fn implementEql(comptime T: type, this: *const T, other: *const T) bool { + const tyinfo = @typeInfo(T); + if (comptime bun.meta.isSimpleEqlType(T)) { + return this.* == other.*; + } + if (comptime T == []const u8) { + return bun.strings.eql(this.*, other.*); + } + if (comptime @typeInfo(T) == .pointer) { + const TT = std.meta.Child(T); + return implementEql(TT, this.*, other.*); + } + if (comptime @typeInfo(T) == .optional) { + const TT = std.meta.Child(T); + if (this.* != null and other.* != null) return implementEql(TT, &this.*.?, &other.*.?); + return false; + } + if (comptime T == VendorPrefix) { + return VendorPrefix.eql(this.*, other.*); + } + return switch (tyinfo) { + .optional => @compileError("Handled above, this means Zack wrote a bug."), + .pointer => @compileError("Handled above, this means Zack wrote a bug."), + .array => { + const Child = std.meta.Child(T); + if (comptime bun.meta.isSimpleEqlType(Child)) { + return std.mem.eql(Child, &this.*, &other.*); + } + if (this.len != other.len) return false; + if (comptime canTransitivelyImplementEql(Child) and @hasDecl(Child, "__generateEql")) { + for (this.*, other.*) |*a, *b| { + if (!implementEql(Child, &a, &b)) return false; + } + } else { + for (this.*, other.*) |*a, *b| { + if (!eql(Child, a, b)) return false; + } + } + return true; + }, + .@"struct" => { + inline for (tyinfo.@"struct".fields) |field| { + if (!eql(field.type, &@field(this, field.name), &@field(other, field.name))) return false; + } + return true; + }, + .@"union" => { + if (tyinfo.@"union".tag_type == null) @compileError("Unions must have a tag type"); + if (@intFromEnum(this.*) != @intFromEnum(other.*)) return false; + const enum_fields = bun.meta.EnumFields(T); + inline for (enum_fields, std.meta.fields(T)) |enum_field, union_field| { + if (enum_field.value == @intFromEnum(this.*)) { + if (union_field.type != void) { + if (comptime canTransitivelyImplementEql(union_field.type) and @hasDecl(union_field.type, "__generateEql")) { + return implementEql(union_field.type, &@field(this, enum_field.name), &@field(other, enum_field.name)); + } + return eql(union_field.type, &@field(this, enum_field.name), &@field(other, enum_field.name)); + } else { + return true; + } + } + } + unreachable; + }, + else => @compileError("Unsupported type: " ++ @typeName(T)), + }; +} + +pub fn implementHash(comptime T: type, this: *const T, hasher: *std.hash.Wyhash) void { + const tyinfo = @typeInfo(T); + if (comptime T == void) return; + if (comptime bun.meta.isSimpleEqlType(T)) { + return hasher.update(std.mem.asBytes(&this)); + } + if (comptime bun.meta.looksLikeListContainerType(T)) |result| { + const list = switch (result) { + .array_list => this.items[0..], + .baby_list => this.sliceConst(), + .small_list => this.slice(), + }; + bun.writeAnyToHasher(hasher, list.len); + for (list) |*item| { + hash(tyinfo.array.child, item, hasher); + } + return; + } + if (comptime T == []const u8) { + return hasher.update(this.*); + } + if (comptime @typeInfo(T) == .pointer) { + @compileError("Invalid type for implementHash(): " ++ @typeName(T)); + } + if (comptime @typeInfo(T) == .optional) { + @compileError("Invalid type for implementHash(): " ++ @typeName(T)); + } + return switch (tyinfo) { + .optional => { + if (this.* == null) { + bun.writeAnyToHasher(hasher, "null"); + } else { + bun.writeAnyToHasher(hasher, "some"); + hash(tyinfo.optional.child, &this.*.?, hasher); + } + }, + .pointer => { + hash(tyinfo.pointer.child, &this.*, hasher); + }, + .array => { + bun.writeAnyToHasher(hasher, this.len); + for (this.*[0..]) |*item| { + hash(tyinfo.array.child, item, hasher); + } + }, + .@"struct" => { + inline for (tyinfo.@"struct".fields) |field| { + if (comptime hasHash(field.type)) { + hash(field.type, &@field(this, field.name), hasher); + } else if (@hasDecl(field.type, "__generateHash") and @typeInfo(field.type) == .@"struct") { + implementHash(field.type, &@field(this, field.name), hasher); + } else { + @compileError("Can't hash these fields: " ++ @typeName(field.type) ++ ". On " ++ @typeName(T)); + } + } + return; + }, + .@"enum" => { + bun.writeAnyToHasher(hasher, @intFromEnum(this.*)); + }, + .@"union" => { + if (tyinfo.@"union".tag_type == null) @compileError("Unions must have a tag type"); + bun.writeAnyToHasher(hasher, @intFromEnum(this.*)); + const enum_fields = bun.meta.EnumFields(T); + inline for (enum_fields, std.meta.fields(T)) |enum_field, union_field| { + if (enum_field.value == @intFromEnum(this.*)) { + const field = union_field; + if (comptime hasHash(field.type)) { + hash(field.type, &@field(this, field.name), hasher); + } else if (@hasDecl(field.type, "__generateHash") and @typeInfo(field.type) == .@"struct") { + implementHash(field.type, &@field(this, field.name), hasher); + } else { + @compileError("Can't hash these fields: " ++ @typeName(field.type) ++ ". On " ++ @typeName(T)); + } + } + } + return; + }, + else => @compileError("Unsupported type: " ++ @typeName(T)), + }; +} pub fn slice(comptime T: type, val: *const T) []const bun.meta.looksLikeListContainerType(T).?.child { if (comptime bun.meta.looksLikeListContainerType(T)) |result| { @@ -39,7 +253,7 @@ pub fn slice(comptime T: type, val: *const T) []const bun.meta.looksLikeListCont pub fn isCompatible(comptime T: type, val: *const T, browsers: bun.css.targets.Browsers) bool { if (@hasDecl(T, "isCompatible")) return T.isCompatible(val, browsers); const tyinfo = @typeInfo(T); - if (tyinfo == .Pointer) { + if (tyinfo == .pointer) { const TT = std.meta.Child(T); return isCompatible(TT, val.*, browsers); } @@ -77,16 +291,16 @@ pub inline fn parseWithOptions(comptime T: type, input: *Parser, options: *const } pub inline fn parse(comptime T: type, input: *Parser) Result(T) { - if (comptime @typeInfo(T) == .Pointer) { + if (comptime @typeInfo(T) == .pointer) { const TT = std.meta.Child(T); return switch (parse(TT, input)) { .result => |v| .{ .result = bun.create(input.allocator(), TT, v) }, .err => |e| .{ .err = e }, }; } - if (comptime @typeInfo(T) == .Optional) { + if (comptime @typeInfo(T) == .optional) { const TT = std.meta.Child(T); - return .{ .result = parse(TT, input).asValue() }; + return .{ .result = input.tryParse(parseFor(TT), .{}).asValue() }; } if (comptime bun.meta.looksLikeListContainerType(T)) |result| { switch (result.list) { @@ -120,11 +334,11 @@ pub inline fn parseFor(comptime T: type) @TypeOf(struct { pub fn hasToCss(comptime T: type) bool { const tyinfo = @typeInfo(T); if (comptime T == []const u8) return false; - if (tyinfo == .Pointer) { + if (tyinfo == .pointer) { const TT = std.meta.Child(T); return hasToCss(TT); } - if (tyinfo == .Optional) { + if (tyinfo == .optional) { const TT = std.meta.Child(T); return hasToCss(TT); } @@ -142,11 +356,11 @@ pub fn hasToCss(comptime T: type) bool { } pub inline fn toCss(comptime T: type, this: *const T, comptime W: type, dest: *Printer(W)) PrintErr!void { - if (@typeInfo(T) == .Pointer) { + if (@typeInfo(T) == .pointer) { const TT = std.meta.Child(T); return toCss(TT, this.*, W, dest); } - if (@typeInfo(T) == .Optional) { + if (@typeInfo(T) == .optional) { const TT = std.meta.Child(T); if (this.*) |*val| { @@ -183,29 +397,30 @@ pub fn eqlList(comptime T: type, lhs: *const ArrayList(T), rhs: *const ArrayList pub fn canTransitivelyImplementEql(comptime T: type) bool { return switch (@typeInfo(T)) { - .Struct, .Union => true, + .@"struct", .@"union" => true, else => false, }; } pub inline fn eql(comptime T: type, lhs: *const T, rhs: *const T) bool { const tyinfo = comptime @typeInfo(T); - if (comptime tyinfo == .Pointer) { + @setEvalBranchQuota(10_000); + if (comptime tyinfo == .pointer) { if (comptime T == []const u8) return bun.strings.eql(lhs.*, rhs.*); - if (comptime tyinfo.Pointer.size == .One) { + if (comptime tyinfo.pointer.size == .one) { const TT = std.meta.Child(T); return eql(TT, lhs.*, rhs.*); - } else if (comptime tyinfo.Pointer.size == .Slice) { + } else if (comptime tyinfo.pointer.size == .slice) { if (lhs.*.len != rhs.*.len) return false; for (lhs.*[0..], rhs.*[0..]) |*a, *b| { - if (!eql(tyinfo.Pointer.child, a, b)) return false; + if (!eql(tyinfo.pointer.child, a, b)) return false; } return true; } else { - @compileError("Unsupported pointer size: " ++ @tagName(tyinfo.Pointer.size) ++ " (" ++ @typeName(T) ++ ")"); + @compileError("Unsupported pointer size: " ++ @tagName(tyinfo.pointer.size) ++ " (" ++ @typeName(T) ++ ")"); } } - if (comptime tyinfo == .Optional) { + if (comptime tyinfo == .optional) { const TT = std.meta.Child(T); if (lhs.* == null and rhs.* == null) return true; if (lhs.* != null and rhs.* != null) return eql(TT, &lhs.*.?, &rhs.*.?); @@ -221,44 +436,47 @@ pub inline fn eql(comptime T: type, lhs: *const T, rhs: *const T) bool { .small_list => lhs.eql(rhs), }; } + if (@hasDecl(T, "IMPL_BITFLAGS")) { + return T.eql(lhs.*, rhs.*); + } return switch (T) { f32 => lhs.* == rhs.*, CSSInteger => lhs.* == rhs.*, CustomIdent, DashedIdent, Ident => bun.strings.eql(lhs.v, rhs.v), []const u8 => bun.strings.eql(lhs.*, rhs.*), - css.VendorPrefix => css.VendorPrefix.eq(lhs.*, rhs.*), + // css.VendorPrefix => css.VendorPrefix.eq(lhs.*, rhs.*), else => T.eql(lhs, rhs), }; } pub fn canTransitivelyImplementDeepClone(comptime T: type) bool { return switch (@typeInfo(T)) { - .Struct, .Union => true, + .@"struct", .@"union" => true, else => false, }; } pub inline fn deepClone(comptime T: type, this: *const T, allocator: Allocator) T { const tyinfo = comptime @typeInfo(T); - if (comptime tyinfo == .Pointer) { - if (comptime tyinfo.Pointer.size == .One) { + if (comptime tyinfo == .pointer) { + if (comptime tyinfo.pointer.size == .one) { const TT = std.meta.Child(T); return bun.create(allocator, TT, deepClone(TT, this.*, allocator)); } - if (comptime tyinfo.Pointer.size == .Slice) { - var slc = allocator.alloc(tyinfo.Pointer.child, this.len) catch bun.outOfMemory(); - if (comptime bun.meta.isSimpleCopyType(tyinfo.Pointer.child) or tyinfo.Pointer.child == []const u8) { + if (comptime tyinfo.pointer.size == .slice) { + var slc = allocator.alloc(tyinfo.pointer.child, this.len) catch bun.outOfMemory(); + if (comptime bun.meta.isSimpleCopyType(tyinfo.pointer.child) or tyinfo.pointer.child == []const u8) { @memcpy(slc, this.*); } else { for (this.*, 0..) |*e, i| { - slc[i] = deepClone(tyinfo.Pointer.child, e, allocator); + slc[i] = deepClone(tyinfo.pointer.child, e, allocator); } } return slc; } - @compileError("Deep clone not supported for this kind of pointer: " ++ @tagName(tyinfo.Pointer.size) ++ " (" ++ @typeName(T) ++ ")"); + @compileError("Deep clone not supported for this kind of pointer: " ++ @tagName(tyinfo.pointer.size) ++ " (" ++ @typeName(T) ++ ")"); } - if (comptime tyinfo == .Optional) { + if (comptime tyinfo == .optional) { const TT = std.meta.Child(T); if (this.* != null) return deepClone(TT, &this.*.?, allocator); return null; @@ -390,11 +608,11 @@ pub fn hasHash(comptime T: type) bool { const tyinfo = @typeInfo(T); if (comptime T == []const u8) return true; if (comptime bun.meta.isSimpleEqlType(T)) return true; - if (tyinfo == .Pointer) { + if (tyinfo == .pointer) { const TT = std.meta.Child(T); return hasHash(TT); } - if (tyinfo == .Optional) { + if (tyinfo == .optional) { const TT = std.meta.Child(T); return hasHash(TT); } @@ -413,11 +631,11 @@ pub fn hasHash(comptime T: type) bool { pub fn hash(comptime T: type, this: *const T, hasher: *std.hash.Wyhash) void { if (comptime T == void) return; const tyinfo = @typeInfo(T); - if (comptime tyinfo == .Pointer and T != []const u8) { + if (comptime tyinfo == .pointer and T != []const u8) { const TT = std.meta.Child(T); - if (tyinfo.Pointer.size == .One) { + if (tyinfo.pointer.size == .one) { return hash(TT, this.*, hasher); - } else if (tyinfo.Pointer.size == .Slice) { + } else if (tyinfo.pointer.size == .slice) { for (this.*) |*item| { hash(TT, item, hasher); } @@ -426,7 +644,7 @@ pub fn hash(comptime T: type, this: *const T, hasher: *std.hash.Wyhash) void { @compileError("Can't hash this pointer type: " ++ @typeName(T)); } } - if (comptime @typeInfo(T) == .Optional) { + if (comptime @typeInfo(T) == .optional) { const TT = std.meta.Child(T); if (this.* != null) return hash(TT, &this.*.?, hasher); return; diff --git a/src/css/media_query.zig b/src/css/media_query.zig index 25a5c58c619d4d..1f4980f42d7e95 100644 --- a/src/css/media_query.zig +++ b/src/css/media_query.zig @@ -708,7 +708,7 @@ pub const MediaFeatureId = enum { /// The non-standard -moz-device-pixel-ratio media feature. @"-moz-device-pixel-ratio", - pub usingnamespace css.DeriveValueType(@This()); + pub usingnamespace css.DeriveValueType(@This(), ValueTypeMap); pub const ValueTypeMap = .{ .width = MediaFeatureType.length, @@ -1510,7 +1510,7 @@ pub fn MediaFeatureName(comptime FeatureId: type) type { // this only works if FeatureId doesn't hold any references to the input string. // i.e. it is an enum comptime { - std.debug.assert(@typeInfo(FeatureId) == .Enum); + std.debug.assert(@typeInfo(FeatureId) == .@"enum"); } input.allocator().free(final_name); }; diff --git a/src/css/prefixes.zig b/src/css/prefixes.zig index 2a9b29edafc83c..dfb384fe545bfc 100644 --- a/src/css/prefixes.zig +++ b/src/css/prefixes.zig @@ -540,7 +540,7 @@ pub const Feature = enum { }, .element => { if (browsers.firefox) |version| { - if (version >= 131072) { + if (version >= 131072 and version <= 8650752) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .moz = true }); } } @@ -641,7 +641,7 @@ pub const Feature = enum { } } if (browsers.ios_saf) |version| { - if (version >= 197120) { + if (version >= 197120 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -651,7 +651,7 @@ pub const Feature = enum { } } if (browsers.safari) |version| { - if (version >= 196864) { + if (version >= 196864 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1146,17 +1146,17 @@ pub const Feature = enum { }, .fill, .fill_available => { if (browsers.chrome) |version| { - if (version >= 1441792) { + if (version >= 1441792 and version <= 8519680) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.android) |version| { - if (version >= 263168) { + if (version >= 263168 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.edge) |version| { - if (version >= 5177344) { + if (version >= 5177344 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1181,7 +1181,7 @@ pub const Feature = enum { } } if (browsers.samsung) |version| { - if (version >= 262144) { + if (version >= 262144 and version <= 1638400) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1225,27 +1225,27 @@ pub const Feature = enum { }, .stretch => { if (browsers.chrome) |version| { - if (version >= 1441792) { + if (version >= 1441792 and version <= 8519680) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.firefox) |version| { - if (version >= 196608) { + if (version >= 196608 and version <= 8650752) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .moz = true }); } } if (browsers.android) |version| { - if (version >= 263168) { + if (version >= 263168 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.edge) |version| { - if (version >= 5177344) { + if (version >= 5177344 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.ios_saf) |version| { - if (version >= 458752) { + if (version >= 458752 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1255,12 +1255,12 @@ pub const Feature = enum { } } if (browsers.safari) |version| { - if (version >= 458752) { + if (version >= 458752 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.samsung) |version| { - if (version >= 327680) { + if (version >= 327680 and version <= 1638400) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1330,7 +1330,7 @@ pub const Feature = enum { }, .text_decoration_skip, .text_decoration_skip_ink => { if (browsers.ios_saf) |version| { - if (version >= 524288) { + if (version >= 524288 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1342,12 +1342,12 @@ pub const Feature = enum { }, .text_decoration => { if (browsers.ios_saf) |version| { - if (version >= 524288) { + if (version >= 524288 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.safari) |version| { - if (version >= 524288) { + if (version >= 524288 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1370,8 +1370,10 @@ pub const Feature = enum { } }, .text_size_adjust => { - if (browsers.firefox != null) { - prefixes = prefixes.bitwiseOr(VendorPrefix{ .moz = true }); + if (browsers.firefox) |version| { + if (version <= 8323072) { + prefixes = prefixes.bitwiseOr(VendorPrefix{ .moz = true }); + } } if (browsers.edge) |version| { if (version >= 786432 and version <= 1179648) { @@ -1384,7 +1386,7 @@ pub const Feature = enum { } } if (browsers.ios_saf) |version| { - if (version >= 327680) { + if (version >= 327680 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1460,22 +1462,22 @@ pub const Feature = enum { }, .box_decoration_break => { if (browsers.chrome) |version| { - if (version >= 1441792) { + if (version >= 1441792 and version <= 8519680) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.android) |version| { - if (version >= 263168) { + if (version >= 263168 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.edge) |version| { - if (version >= 5177344) { + if (version >= 5177344 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.ios_saf) |version| { - if (version >= 458752) { + if (version >= 458752 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1485,12 +1487,12 @@ pub const Feature = enum { } } if (browsers.safari) |version| { - if (version >= 393472) { + if (version >= 393472 and version <= 1179648) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.samsung) |version| { - if (version >= 262144) { + if (version >= 262144 and version <= 1638400) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1848,17 +1850,17 @@ pub const Feature = enum { }, .cross_fade => { if (browsers.chrome) |version| { - if (version >= 1114112) { + if (version >= 1114112 and version <= 8519680) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.android) |version| { - if (version >= 263168) { + if (version >= 263168 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.edge) |version| { - if (version >= 5177344) { + if (version >= 5177344 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -1878,7 +1880,7 @@ pub const Feature = enum { } } if (browsers.samsung) |version| { - if (version >= 262144) { + if (version >= 262144 and version <= 1638400) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -2065,17 +2067,17 @@ pub const Feature = enum { }, .print_color_adjust, .color_adjust => { if (browsers.chrome) |version| { - if (version >= 1114112) { + if (version >= 1114112 and version <= 8519680) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.android) |version| { - if (version >= 263168) { + if (version >= 263168 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } if (browsers.edge) |version| { - if (version >= 5177344) { + if (version >= 5177344 and version <= 8323072) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } @@ -2100,7 +2102,7 @@ pub const Feature = enum { } } if (browsers.samsung) |version| { - if (version >= 262144) { + if (version >= 262144 and version <= 1638400) { prefixes = prefixes.bitwiseOr(VendorPrefix{ .webkit = true }); } } diff --git a/src/css/printer.zig b/src/css/printer.zig index c50adb3bcde426..b68c1086bb54b8 100644 --- a/src/css/printer.zig +++ b/src/css/printer.zig @@ -160,6 +160,18 @@ pub fn Printer(comptime Writer: type) type { return PrintErr.lol; } + pub fn addInvalidCssModulesPatternInGridError(this: *This) PrintErr!void { + this.error_kind = css.PrinterError{ + .kind = .invalid_css_modules_pattern_in_grid, + .loc = css.ErrorLocation{ + .filename = this.filename(), + .line = this.loc.line, + .column = this.loc.column, + }, + }; + return PrintErr.lol; + } + /// Returns an error of the given kind at the provided location in the current source file. pub fn newError( this: *This, diff --git a/src/css/properties/align.zig b/src/css/properties/align.zig index d5f3f5b716c744..60e6a68eb357af 100644 --- a/src/css/properties/align.zig +++ b/src/css/properties/align.zig @@ -10,6 +10,10 @@ const PrintErr = css.PrintErr; const LengthPercentage = css.css_values.length.LengthPercentage; +const VendorPrefix = css.VendorPrefix; +const Property = css.Property; +const Feature = css.prefixes.Feature; + /// A value for the [align-content](https://www.w3.org/TR/css-align-3/#propdef-align-content) property. pub const AlignContent = union(enum) { /// Default alignment. @@ -35,7 +39,8 @@ pub const AlignContent = union(enum) { pub fn __generateToCss() void {} pub fn parse(input: *css.Parser) css.Result(@This()) { - const overflow = OverflowPosition.parse(input).asValue(); + const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue(); + const value = switch (ContentPosition.parse(input)) { .result => |v| v, .err => |e| return .{ .err = e }, @@ -174,16 +179,16 @@ pub const JustifyContent = union(enum) { }, pub fn parse(input: *css.Parser) css.Result(@This()) { - if (input.expectIdentMatching("normal").isOk()) { + if (input.tryParse(css.Parser.expectIdentMatching, .{"normal"}).isOk()) { return .{ .result = .normal }; } - if (ContentDistribution.parse(input).asValue()) |val| { + if (input.tryParse(ContentDistribution.parse, .{}).asValue()) |val| { return .{ .result = .{ .content_distribution = val } }; } - const overflow = OverflowPosition.parse(input).asValue(); - if (ContentPosition.parse(input).asValue()) |content_position| { + const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue(); + if (input.tryParse(ContentPosition.parse, .{}).asValue()) |content_position| { return .{ .result = .{ .content_position = .{ .overflow = overflow, @@ -281,7 +286,7 @@ pub const AlignSelf = union(enum) { } pub fn parse(input: *css.Parser) css.Result(@This()) { - const overflow = OverflowPosition.parse(input).asValue(); + const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue(); const self_position = switch (SelfPosition.parse(input)) { .result => |v| v, .err => |e| return .{ .err = e }, @@ -465,7 +470,7 @@ pub const AlignItems = union(enum) { } pub fn parse(input: *css.Parser) css.Result(@This()) { - const overflow = OverflowPosition.parse(input).asValue(); + const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue(); const self_position = switch (SelfPosition.parse(input)) { .result => |v| v, .err => |e| return .{ .err = e }, @@ -742,7 +747,7 @@ pub const Gap = struct { /// The column gap. column: GapValue, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.gap); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.gap, PropertyFieldMap); pub const PropertyFieldMap = .{ .row = "row-gap", @@ -785,7 +790,7 @@ pub const PlaceItems = struct { /// The item justification. justify: JustifyItems, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"place-items"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"place-items", PropertyFieldMap); pub const PropertyFieldMap = .{ .@"align" = "align-items", @@ -857,7 +862,7 @@ pub const PlaceSelf = struct { /// The item justification. justify: JustifySelf, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"place-self"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"place-self", PropertyFieldMap); pub const PropertyFieldMap = .{ .@"align" = "align-self", @@ -951,7 +956,7 @@ pub const PlaceContent = struct { /// The content justification. justify: JustifyContent, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"place-content"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"place-content", PropertyFieldMap); pub const PropertyFieldMap = .{ .@"align" = css.PropertyIdTag.@"align-content", @@ -1083,3 +1088,420 @@ pub const ContentPositionInner = struct { return css.implementEql(@This(), lhs, rhs); } }; + +const FlexLinePack = css.css_properties.flex.FlexLinePack; +const BoxPack = css.css_properties.flex.BoxPack; +const FlexPack = css.css_properties.flex.FlexPack; +const BoxAlign = css.css_properties.flex.BoxAlign; +const FlexAlign = css.css_properties.flex.FlexAlign; +const FlexItemAlign = css.css_properties.flex.FlexItemAlign; + +pub const AlignHandler = struct { + align_content: ?struct { AlignContent, VendorPrefix } = null, + flex_line_pack: ?struct { FlexLinePack, VendorPrefix } = null, + justify_content: ?struct { JustifyContent, VendorPrefix } = null, + box_pack: ?struct { BoxPack, VendorPrefix } = null, + flex_pack: ?struct { FlexPack, VendorPrefix } = null, + align_self: ?struct { AlignSelf, VendorPrefix } = null, + flex_item_align: ?struct { FlexItemAlign, VendorPrefix } = null, + justify_self: ?JustifySelf = null, + align_items: ?struct { AlignItems, VendorPrefix } = null, + box_align: ?struct { BoxAlign, VendorPrefix } = null, + flex_align: ?struct { FlexAlign, VendorPrefix } = null, + justify_items: ?JustifyItems = null, + row_gap: ?GapValue = null, + column_gap: ?GapValue = null, + has_any: bool = false, + + pub fn handleProperty(this: *AlignHandler, property: *const Property, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) bool { + switch (property.*) { + .@"align-content" => |*val| { + this.flex_line_pack = null; + this.handlePropertyHelper(dest, context, "align_content", &val.*[0], val.*[1]); + }, + .@"flex-line-pack" => |*val| this.handlePropertyHelper(dest, context, "flex_line_pack", &val.*[0], val.*[1]), + .@"justify-content" => |*val| { + this.box_pack = null; + this.flex_pack = null; + this.handlePropertyHelper(dest, context, "justify_content", &val.*[0], val.*[1]); + }, + .@"box-pack" => |*val| this.handlePropertyHelper(dest, context, "box_pack", &val.*[0], val.*[1]), + .@"flex-pack" => |*val| this.handlePropertyHelper(dest, context, "flex_pack", &val.*[0], val.*[1]), + .@"place-content" => |*val| { + this.flex_line_pack = null; + this.box_pack = null; + this.flex_pack = null; + this.handlePropertyMaybeFlush(dest, context, "align_content", &val.@"align", VendorPrefix.NONE); + this.handlePropertyMaybeFlush(dest, context, "justify_content", &val.justify, VendorPrefix.NONE); + this.handlePropertyHelper(dest, context, "align_content", &val.@"align", VendorPrefix.NONE); + this.handlePropertyHelper(dest, context, "justify_content", &val.justify, VendorPrefix.NONE); + }, + .@"align-self" => |*val| { + this.flex_item_align = null; + this.handlePropertyHelper(dest, context, "align_self", &val.*[0], val.*[1]); + }, + .@"flex-item-align" => |*val| this.handlePropertyHelper(dest, context, "flex_item_align", &val.*[0], val.*[1]), + .@"justify-self" => |*val| { + this.justify_self = css.generic.deepClone(@TypeOf(val.*), val, context.allocator); + this.has_any = true; + }, + .@"place-self" => |*val| { + this.flex_item_align = null; + this.handlePropertyHelper(dest, context, "align_self", &val.@"align", VendorPrefix.NONE); + this.justify_self = css.generic.deepClone(@TypeOf(val.justify), &val.justify, context.allocator); + }, + .@"align-items" => |*val| { + this.box_align = null; + this.flex_align = null; + this.handlePropertyHelper(dest, context, "align_items", &val.*[0], val.*[1]); + }, + .@"box-align" => |*val| this.handlePropertyHelper(dest, context, "box_align", &val.*[0], val.*[1]), + .@"flex-align" => |*val| this.handlePropertyHelper(dest, context, "flex_align", &val.*[0], val.*[1]), + .@"justify-items" => |*val| { + this.justify_items = css.generic.deepClone(@TypeOf(val.*), val, context.allocator); + this.has_any = true; + }, + .@"place-items" => |*val| { + this.box_align = null; + this.flex_align = null; + this.handlePropertyHelper(dest, context, "align_items", &val.@"align", VendorPrefix.NONE); + this.justify_items = css.generic.deepClone(@TypeOf(val.justify), &val.justify, context.allocator); + }, + .@"row-gap" => |*val| { + this.row_gap = css.generic.deepClone(@TypeOf(val.*), val, context.allocator); + this.has_any = true; + }, + .@"column-gap" => |*val| { + this.column_gap = css.generic.deepClone(@TypeOf(val.*), val, context.allocator); + this.has_any = true; + }, + .gap => |*val| { + this.row_gap = css.generic.deepClone(@TypeOf(val.row), &val.row, context.allocator); + this.column_gap = css.generic.deepClone(@TypeOf(val.column), &val.column, context.allocator); + this.has_any = true; + }, + .unparsed => |*val| { + if (isAlignProperty(val.property_id)) { + this.flush(dest, context); + dest.append(context.allocator, property.*) catch bun.outOfMemory(); + } else { + return false; + } + }, + else => return false, + } + + return true; + } + + pub fn finalize(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + this.flush(dest, context); + } + + fn flush(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + if (!this.has_any) { + return; + } + + this.has_any = false; + + var align_content = bun.take(&this.align_content); + var justify_content = bun.take(&this.justify_content); + var align_self = bun.take(&this.align_self); + var justify_self = bun.take(&this.justify_self); + var align_items = bun.take(&this.align_items); + var justify_items = bun.take(&this.justify_items); + const row_gap = bun.take(&this.row_gap); + const column_gap = bun.take(&this.column_gap); + var box_align = bun.take(&this.box_align); + var box_pack = bun.take(&this.box_pack); + var flex_line_pack = bun.take(&this.flex_line_pack); + var flex_pack = bun.take(&this.flex_pack); + var flex_align = bun.take(&this.flex_align); + var flex_item_align = bun.take(&this.flex_item_align); + + // 2009 properties + this.flushPrefixedProperty(dest, context, "box-align", bun.take(&box_align)); + this.flushPrefixedProperty(dest, context, "box-pack", bun.take(&box_pack)); + + // 2012 properties + this.flushPrefixedProperty(dest, context, "flex-pack", bun.take(&flex_pack)); + this.flushPrefixedProperty(dest, context, "flex-align", bun.take(&flex_align)); + this.flushPrefixedProperty(dest, context, "flex-item-align", bun.take(&flex_item_align)); + this.flushPrefixedProperty(dest, context, "flex-line-pack", bun.take(&flex_line_pack)); + + this.flushLegacyProperty(dest, context, Feature.align_content, &align_content, null, .{ FlexLinePack, "flex-line-pack" }); + this.flushLegacyProperty(dest, context, Feature.justify_content, &justify_content, .{ BoxPack, "box-pack" }, .{ FlexPack, "flex-pack" }); + if (context.targets.isCompatible(.place_content)) { + this.flushShorthandHelper( + dest, + context, + .{ .prop = "place-content", .ty = PlaceContent }, + .{ .feature = Feature.align_content, .prop = "align-content" }, + &align_content, + &justify_content, + .{ .feature = Feature.justify_content, .prop = "justify-content" }, + ); + } + this.flushStandardPropertyHelper(dest, context, "align-content", bun.take(&align_content), Feature.align_content); + this.flushStandardPropertyHelper(dest, context, "justify-content", bun.take(&justify_content), Feature.justify_content); + + this.flushLegacyProperty(dest, context, Feature.align_self, &align_self, null, .{ FlexItemAlign, "flex-item-align" }); + if (context.targets.isCompatible(.place_self)) { + this.flushShorthandHelper(dest, context, .{ .prop = "place-self", .ty = PlaceSelf }, .{ .feature = Feature.align_self, .prop = "align-self" }, &align_self, &justify_self, null); + } + this.flushStandardPropertyHelper(dest, context, "align-self", bun.take(&align_self), Feature.align_self); + this.flushUnprefixProperty(dest, context, "justify-self", bun.take(&justify_self)); + + this.flushLegacyProperty(dest, context, Feature.align_items, &align_items, .{ BoxAlign, "box-align" }, .{ FlexAlign, "flex-align" }); + if (context.targets.isCompatible(css.compat.Feature.place_items)) { + this.flushShorthandHelper(dest, context, .{ .prop = "place-items", .ty = PlaceItems }, .{ .feature = Feature.align_items, .prop = "align-items" }, &align_items, &justify_items, null); + } + this.flushStandardPropertyHelper(dest, context, "align-items", bun.take(&align_items), Feature.align_items); + this.flushUnprefixProperty(dest, context, "justify-items", bun.take(&justify_items)); + + if (row_gap != null and column_gap != null) { + dest.append(context.allocator, Property{ .gap = Gap{ + .row = row_gap.?, + .column = column_gap.?, + } }) catch bun.outOfMemory(); + } else { + if (row_gap != null) { + dest.append(context.allocator, Property{ .@"row-gap" = row_gap.? }) catch bun.outOfMemory(); + } + + if (column_gap != null) { + dest.append(context.allocator, Property{ .@"column-gap" = column_gap.? }) catch bun.outOfMemory(); + } + } + } + + fn handlePropertyMaybeFlush(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, val: anytype, vp: VendorPrefix) void { + // If two vendor prefixes for the same property have different + // values, we need to flush what we have immediately to preserve order. + if (@field(this, prop)) |*v| { + if (!val.eql(&v[0]) and !v[1].contains(vp)) { + this.flush(dest, context); + } + } + } + + fn handlePropertyHelper(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, val: anytype, vp: VendorPrefix) void { + this.handlePropertyMaybeFlush(dest, context, prop, val, vp); + // Otherwise, update the value and add the prefix. + if (@field(this, prop)) |*tuple| { + tuple.*[0] = css.generic.deepClone(@TypeOf(val.*), val, context.allocator); + tuple.*[1].insert(vp); + } else { + @field(this, prop) = .{ css.generic.deepClone(@TypeOf(val.*), val, context.allocator), vp }; + this.has_any = true; + } + } + + // Gets prefixes for standard properties. + fn flushPrefixesHelper(_: *AlignHandler, context: *css.PropertyHandlerContext, comptime feature: Feature) VendorPrefix { + var prefix = context.targets.prefixes(VendorPrefix.NONE, feature); + // Firefox only implemented the 2009 spec prefixed. + // Microsoft only implemented the 2012 spec prefixed. + prefix.remove(VendorPrefix{ + .moz = true, + .ms = true, + }); + return prefix; + } + + fn flushStandardPropertyHelper(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, key: anytype, comptime feature: Feature) void { + if (key) |v| { + const val = v[0]; + var prefix = v[1]; + // If we have an unprefixed property, override necessary prefixes. + prefix = if (prefix.contains(VendorPrefix.NONE)) flushPrefixesHelper(this, context, feature) else prefix; + dest.append(context.allocator, @unionInit(Property, prop, .{ val, prefix })) catch bun.outOfMemory(); + } + } + + fn flushLegacyProperty( + this: *AlignHandler, + dest: *css.DeclarationList, + context: *css.PropertyHandlerContext, + comptime feature: Feature, + key: anytype, + comptime prop_2009: ?struct { type, []const u8 }, + comptime prop_2012: ?struct { type, []const u8 }, + ) void { + _ = this; // autofix + if (key.*) |v| { + const val = v[0]; + var prefix = v[1]; + // If we have an unprefixed standard property, generate legacy prefixed versions. + prefix = context.targets.prefixes(prefix, feature); + + if (prefix.contains(VendorPrefix.NONE)) { + if (comptime prop_2009) |p2009| { + // 2009 spec, implemented by webkit and firefox. + if (context.targets.browsers) |targets| { + var prefixes_2009 = VendorPrefix.empty(); + if (Feature.isFlex2009(targets)) { + prefixes_2009.insert(VendorPrefix.WEBKIT); + } + if (prefix.contains(VendorPrefix.MOZ)) { + prefixes_2009.insert(VendorPrefix.MOZ); + } + if (!prefixes_2009.isEmpty()) { + const s = brk: { + const T = comptime p2009[0]; + if (comptime T == css.css_properties.flex.BoxOrdinalGroup) break :brk @as(?i32, val); + break :brk p2009[0].fromStandard(&val); + }; + if (s) |a| { + dest.append(context.allocator, @unionInit(Property, p2009[1], .{ + a, + prefixes_2009, + })) catch bun.outOfMemory(); + } + } + } + } + } + + // 2012 spec, implemented by microsoft. + if (prefix.contains(VendorPrefix.MS)) { + if (comptime prop_2012) |p2012| { + const s = brk: { + const T = comptime p2012[0]; + if (comptime T == css.css_properties.flex.BoxOrdinalGroup) break :brk @as(?i32, val); + break :brk p2012[0].fromStandard(&val); + }; + if (s) |q| { + dest.append(context.allocator, @unionInit(Property, p2012[1], .{ + q, + VendorPrefix.MS, + })) catch bun.outOfMemory(); + } + } + } + + // Remove Firefox and IE from standard prefixes. + prefix.remove(VendorPrefix.MOZ); + prefix.remove(VendorPrefix.MS); + } + } + + fn flushPrefixedProperty(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, key: anytype) void { + _ = this; // autofix + if (key) |v| { + const val = v[0]; + const prefix = v[1]; + dest.append(context.allocator, @unionInit(Property, prop, .{ val, prefix })) catch bun.outOfMemory(); + } + } + + fn flushUnprefixProperty(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, key: anytype) void { + _ = this; // autofix + if (key) |v| { + const val = v; + dest.append(context.allocator, @unionInit(Property, prop, val)) catch bun.outOfMemory(); + } + } + + fn flushShorthandHelper( + this: *AlignHandler, + dest: *css.DeclarationList, + context: *css.PropertyHandlerContext, + comptime prop: struct { prop: []const u8, ty: type }, + comptime align_prop: struct { + feature: Feature, + prop: []const u8, + }, + align_val: anytype, + justify_val: anytype, + comptime justify_prop: ?struct { + feature: Feature, + prop: []const u8, + }, + ) void { + // Only use shorthand if both align and justify are present + if (align_val.*) |*__v1| { + const @"align" = &__v1.*[0]; + const align_prefix: *css.VendorPrefix = &__v1.*[1]; + if (justify_val.*) |*__v2| { + const justify = __v2; + + const intersection = align_prefix.bitwiseAnd(if (comptime justify_prop != null) __v2.*[1] else align_prefix.*); + // Only use shorthand if unprefixed. + if (intersection.contains(VendorPrefix.NONE)) { + // Add prefixed longhands if needed. + align_prefix.* = flushPrefixesHelper(this, context, align_prop.feature); + align_prefix.remove(VendorPrefix.NONE); + if (!align_prefix.isEmpty()) { + dest.append( + context.allocator, + @unionInit(Property, align_prop.prop, .{ css.generic.deepClone(@TypeOf(@"align".*), @"align", context.allocator), align_prefix.* }), + ) catch bun.outOfMemory(); + } + + if (comptime justify_prop != null) { + const justify_actual = &__v2.*[0]; + const justify_prefix = &__v2.*[1]; + justify_prefix.* = this.flushPrefixesHelper(context, justify_prop.?.feature); + justify_prefix.remove(css.VendorPrefix.NONE); + + if (!justify_prefix.isEmpty()) { + dest.append( + context.allocator, + @unionInit(Property, justify_prop.?.prop, .{ css.generic.deepClone(@TypeOf(justify_actual.*), justify_actual, context.allocator), justify_prefix.* }), + ) catch bun.outOfMemory(); + } + + // Add shorthand. + dest.append( + context.allocator, + @unionInit(Property, prop.prop, prop.ty{ + .@"align" = css.generic.deepClone(@TypeOf(@"align".*), @"align", context.allocator), + .justify = css.generic.deepClone(@TypeOf(justify_actual.*), justify_actual, context.allocator), + }), + ) catch bun.outOfMemory(); + } else { + + // Add shorthand. + dest.append( + context.allocator, + @unionInit(Property, prop.prop, prop.ty{ + .@"align" = css.generic.deepClone(@TypeOf(@"align".*), @"align", context.allocator), + .justify = css.generic.deepClone(@TypeOf(justify.*), justify, context.allocator), + }), + ) catch bun.outOfMemory(); + } + + align_val.* = null; + justify_val.* = null; + } + } + } + } +}; + +fn isAlignProperty(property_id: css.PropertyId) bool { + return switch (property_id) { + .@"align-content", + .@"flex-line-pack", + .@"justify-content", + .@"box-pack", + .@"flex-pack", + .@"place-content", + .@"align-self", + .@"flex-item-align", + .@"justify-self", + .@"place-self", + .@"align-items", + .@"box-align", + .@"flex-align", + .@"justify-items", + .@"place-items", + .@"row-gap", + .@"column-gap", + .gap, + => true, + else => false, + }; +} diff --git a/src/css/properties/animation.zig b/src/css/properties/animation.zig index d6d8fb198f4820..aed8627d781ce4 100644 --- a/src/css/properties/animation.zig +++ b/src/css/properties/animation.zig @@ -16,6 +16,8 @@ const CSSNumber = css.css_values.number.CSSNumber; const LengthPercentageOrAuto = css.css_values.length.LengthPercentageOrAuto; const Size2D = css.css_values.size.Size2D; const DashedIdent = css.css_values.ident.DashedIdent; +const Time = css.css_values.time.Time; +const EasingFunction = css.css_values.easing.EasingFunction; /// A list of animations. pub const AnimationList = SmallList(Animation, 1); @@ -24,7 +26,198 @@ pub const AnimationList = SmallList(Animation, 1); pub const AnimationNameList = SmallList(AnimationName, 1); /// A value for the [animation](https://drafts.csswg.org/css-animations/#animation) shorthand property. -pub const Animation = @compileError(css.todo_stuff.depth); +pub const Animation = struct { + /// The animation name. + name: AnimationName, + /// The animation duration. + duration: Time, + /// The easing function for the animation. + timing_function: EasingFunction, + /// The number of times the animation will run. + iteration_count: AnimationIterationCount, + /// The direction of the animation. + direction: AnimationDirection, + /// The current play state of the animation. + play_state: AnimationPlayState, + /// The animation delay. + delay: Time, + /// The animation fill mode. + fill_mode: AnimationFillMode, + /// The animation timeline. + timeline: AnimationTimeline, + + pub usingnamespace css.DefineListShorthand(@This()); + + pub const PropertyFieldMap = .{ + .name = css.PropertyIdTag.@"animation-name", + .duration = css.PropertyIdTag.@"animation-duration", + .timing_function = css.PropertyIdTag.@"animation-timing-function", + .iteration_count = css.PropertyIdTag.@"animation-iteration-count", + .direction = css.PropertyIdTag.@"animation-direction", + .play_state = css.PropertyIdTag.@"animation-play-state", + .delay = css.PropertyIdTag.@"animation-delay", + .fill_mode = css.PropertyIdTag.@"animation-fill-mode", + .timeline = css.PropertyIdTag.@"animation-timeline", + }; + + pub const VendorPrefixMap = .{ + .name = true, + .duration = true, + .timing_function = true, + .iteration_count = true, + .direction = true, + .play_state = true, + .delay = true, + .fill_mode = true, + }; + + pub fn parse(input: *css.Parser) css.Result(@This()) { + var name: ?AnimationName = null; + var duration: ?Time = null; + var timing_function: ?EasingFunction = null; + var iteration_count: ?AnimationIterationCount = null; + var direction: ?AnimationDirection = null; + var play_state: ?AnimationPlayState = null; + var delay: ?Time = null; + var fill_mode: ?AnimationFillMode = null; + var timeline: ?AnimationTimeline = null; + + while (true) { + if (duration == null) { + if (input.tryParse(Time.parse, .{})) |value| { + duration = value; + continue; + } + } + if (timing_function == null) { + if (input.tryParse(EasingFunction.parse, .{})) |value| { + timing_function = value; + continue; + } + } + if (delay == null) { + if (input.tryParse(Time.parse, .{})) |value| { + delay = value; + continue; + } + } + if (iteration_count == null) { + if (input.tryParse(AnimationIterationCount.parse, .{})) |value| { + iteration_count = value; + continue; + } + } + if (direction == null) { + if (input.tryParse(AnimationDirection.parse, .{})) |value| { + direction = value; + continue; + } + } + if (fill_mode == null) { + if (input.tryParse(AnimationFillMode.parse, .{})) |value| { + fill_mode = value; + continue; + } + } + if (play_state == null) { + if (input.tryParse(AnimationPlayState.parse, .{})) |value| { + play_state = value; + continue; + } + } + if (name == null) { + if (input.tryParse(AnimationName.parse, .{})) |value| { + name = value; + continue; + } + } + if (timeline == null) { + if (input.tryParse(AnimationTimeline.parse, .{})) |value| { + timeline = value; + continue; + } + } + break; + } + + return .{ + .result = Animation{ + .name = name orelse AnimationName.none, + .duration = duration orelse Time{ .seconds = 0.0 }, + .timing_function = timing_function orelse EasingFunction.ease, + .iteration_count = iteration_count orelse AnimationIterationCount.number(1), + .direction = direction orelse AnimationDirection.normal, + .play_state = play_state orelse AnimationPlayState.running, + .delay = delay orelse Time{ .seconds = 0.0 }, + .fill_mode = fill_mode orelse AnimationFillMode.none, + .timeline = timeline orelse AnimationTimeline.auto, + }, + }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *Printer(W)) PrintErr!void { + switch (this.name) { + .none => {}, + inline .ident, .string => |name| { + const name_str = if (this.name == .ident) name.v else name; + + if (!this.duration.isZero() or !this.delay.isZero()) { + try this.duration.toCss(W, dest); + try dest.writeChar(' '); + } + + if (!this.timing_function.isEase() or EasingFunction.isIdent(name_str)) { + try this.timing_function.toCss(W, dest); + try dest.writeChar(' '); + } + + if (!this.delay.isZero()) { + try this.delay.toCss(W, dest); + try dest.writeChar(' '); + } + + if (!this.iteration_count.eql(&AnimationIterationCount.default()) or bun.strings.eqlCaseInsensitiveASCII(name_str, "infinite")) { + try this.iteration_count.toCss(W, dest); + try dest.writeChar(' '); + } + + if (!this.direction.eql(&AnimationDirection.default()) or css.parse_utility.parseString( + dest.allocator, + AnimationDirection, + name_str, + AnimationDirection.parse, + ).isOk()) { + try this.direction.toCss(W, dest); + try dest.writeChar(' '); + } + + if (!this.fill_mode.eql(&AnimationFillMode.default()) or + (!bun.strings.eqlCaseInsensitiveASCII(name_str, "none") and css.parse_utility.parseString(dest.allocator, AnimationFillMode, name_str, AnimationFillMode.parse).isOk())) + { + try this.fill_mode.toCss(W, dest); + try dest.writeChar(' '); + } + + if (!this.play_state.eql(&AnimationPlayState.default()) or css.parse_utility.parseString( + dest.allocator, + AnimationPlayState, + name_str, + AnimationPlayState.parse, + ).isOk()) { + try this.play_state.toCss(W, dest); + try dest.writeChar(' '); + } + }, + } + + try this.name.toCss(W, dest); + + if (!this.name.eql(&AnimationName.none) and !this.timeline.eql(&AnimationTimeline.default())) { + try dest.writeChar(' '); + try this.timeline.toCss(W, dest); + } + } +}; /// A value for the [animation-name](https://drafts.csswg.org/css-animations/#animation-name) property. pub const AnimationName = union(enum) { @@ -94,19 +287,80 @@ pub const AnimationIterationCount = union(enum) { number: CSSNumber, /// The animation will repeat forever. infinite, + + pub usingnamespace css.DeriveParse(@This()); + pub usingnamespace css.DeriveToCss(@This()); + + pub fn default() AnimationIterationCount { + return .{ .number = 1.0 }; + } + + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } }; /// A value for the [animation-direction](https://drafts.csswg.org/css-animations/#animation-direction) property. -pub const AnimationDirection = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const AnimationDirection = enum { + /// The animation is played as specified + normal, + /// The animation is played in reverse. + reverse, + /// The animation iterations alternate between forward and reverse. + alternate, + /// The animation iterations alternate between forward and reverse, with reverse occurring first. + @"alternate-reverse", + + pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn default() AnimationDirection { + return .normal; + } +}; /// A value for the [animation-play-state](https://drafts.csswg.org/css-animations/#animation-play-state) property. -pub const AnimationPlayState = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const AnimationPlayState = enum { + /// The animation is playing. + running, + /// The animation is paused. + paused, + + pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn default() AnimationPlayState { + return .running; + } +}; /// A value for the [animation-fill-mode](https://drafts.csswg.org/css-animations/#animation-fill-mode) property. -pub const AnimationFillMode = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const AnimationFillMode = enum { + /// The animation has no effect while not playing. + none, + /// After the animation, the ending values are applied. + forwards, + /// Before the animation, the starting values are applied. + backwards, + /// Both forwards and backwards apply. + both, + + pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn default() AnimationFillMode { + return .none; + } +}; /// A value for the [animation-composition](https://drafts.csswg.org/css-animations-2/#animation-composition) property. -pub const AnimationComposition = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const AnimationComposition = enum { + /// The result of compositing the effect value with the underlying value is simply the effect value. + replace, + /// The effect value is added to the underlying value. + add, + /// The effect value is accumulated onto the underlying value. + accumulate, + + pub usingnamespace css.DefineEnumProperty(@This()); +}; /// A value for the [animation-timeline](https://drafts.csswg.org/css-animations-2/#animation-timeline) property. pub const AnimationTimeline = union(enum) { @@ -120,6 +374,17 @@ pub const AnimationTimeline = union(enum) { scroll: ScrollTimeline, /// The view() function. view: ViewTimeline, + + pub usingnamespace css.DeriveParse(@This()); + pub usingnamespace css.DeriveToCss(@This()); + + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } + + pub fn default() AnimationTimeline { + return .auto; + } }; /// The [scroll()](https://drafts.csswg.org/scroll-animations-1/#scroll-notation) function. @@ -139,10 +404,38 @@ pub const ViewTimeline = struct { }; /// A scroller, used in the `scroll()` function. -pub const Scroller = @compileError(css.todo_stuff.depth); +pub const Scroller = enum { + /// Specifies to use the document viewport as the scroll container. + root, + /// Specifies to use the nearest ancestor scroll container. + nearest, + /// Specifies to use the element's own principal box as the scroll container. + self, + + pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn default() Scroller { + return .nearest; + } +}; /// A scroll axis, used in the `scroll()` function. -pub const ScrollAxis = @compileError(css.todo_stuff.depth); +pub const ScrollAxis = enum { + /// Specifies to use the measure of progress along the block axis of the scroll container. + block, + /// Specifies to use the measure of progress along the inline axis of the scroll container. + @"inline", + /// Specifies to use the measure of progress along the horizontal axis of the scroll container. + x, + /// Specifies to use the measure of progress along the vertical axis of the scroll container. + y, + + pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn default() ScrollAxis { + return .block; + } +}; /// A value for the animation-range shorthand property. pub const AnimationRange = struct { diff --git a/src/css/properties/background.zig b/src/css/properties/background.zig index 2447a370fa6d68..2946f44b083bdc 100644 --- a/src/css/properties/background.zig +++ b/src/css/properties/background.zig @@ -524,63 +524,54 @@ pub const AspectRatio = struct { }; pub const BackgroundProperty = packed struct(u16) { - @"background-color": bool = false, - @"background-image": bool = false, - @"background-position-x": bool = false, - @"background-position-y": bool = false, - @"background-repeat": bool = false, - @"background-size": bool = false, - @"background-attachment": bool = false, - @"background-origin": bool = false, - @"background-clip": bool = false, + color: bool = false, + image: bool = false, + @"position-x": bool = false, + @"position-y": bool = false, + repeat: bool = false, + size: bool = false, + attachment: bool = false, + origin: bool = false, + clip: bool = false, __unused: u7 = 0, pub usingnamespace css.Bitflags(@This()); - pub const @"background-color" = BackgroundProperty{ .@"background-color" = true }; - pub const @"background-image" = BackgroundProperty{ .@"background-image" = true }; - pub const @"background-position-x" = BackgroundProperty{ .@"background-position-x" = true }; - pub const @"background-position-y" = BackgroundProperty{ .@"background-position-y" = true }; - pub const @"background-position" = BackgroundProperty{ .@"background-position-x" = true, .@"background-position-y" = true }; - pub const @"background-repeat" = BackgroundProperty{ .@"background-repeat" = true }; - pub const @"background-size" = BackgroundProperty{ .@"background-size" = true }; - pub const @"background-attachment" = BackgroundProperty{ .@"background-attachment" = true }; - pub const @"background-origin" = BackgroundProperty{ .@"background-origin" = true }; - pub const @"background-clip" = BackgroundProperty{ .@"background-clip" = true }; + pub const @"background-color" = BackgroundProperty{ .color = true }; + pub const @"background-image" = BackgroundProperty{ .image = true }; + pub const @"background-position-x" = BackgroundProperty{ .@"position-x" = true }; + pub const @"background-position-y" = BackgroundProperty{ .@"position-y" = true }; + pub const @"background-position" = BackgroundProperty{ .@"position-x" = true, .@"position-y" = true }; + pub const @"background-repeat" = BackgroundProperty{ .repeat = true }; + pub const @"background-size" = BackgroundProperty{ .size = true }; + pub const @"background-attachment" = BackgroundProperty{ .attachment = true }; + pub const @"background-origin" = BackgroundProperty{ .origin = true }; + pub const @"background-clip" = BackgroundProperty{ .clip = true }; + pub const background = BackgroundProperty{ - .@"background-color" = true, - .@"background-image" = true, - .@"background-position-x" = true, - .@"background-position-y" = true, - .@"background-repeat" = true, - .@"background-size" = true, - .@"background-attachment" = true, - .@"background-origin" = true, - .@"background-clip" = true, + .color = true, + .image = true, + .@"position-x" = true, + .@"position-y" = true, + .repeat = true, + .size = true, + .attachment = true, + .origin = true, + .clip = true, }; - pub fn fromPropertyId(property_id: css.PropertyId) ?BackgroundProperty { + pub fn tryFromPropertyId(property_id: css.PropertyId) ?BackgroundProperty { return switch (property_id) { - .@"background-color" => BackgroundProperty{ .@"background-color" = true }, - .@"background-image" => BackgroundProperty{ .@"background-image" = true }, - .@"background-position-x" => BackgroundProperty{ .@"background-position-x" = true }, - .@"background-position-y" => BackgroundProperty{ .@"background-position-y" = true }, - .@"background-position" => BackgroundProperty{ .@"background-position-x" = true, .@"background-position-y" = true }, - .@"background-repeat" => BackgroundProperty{ .@"background-repeat" = true }, - .@"background-size" => BackgroundProperty{ .@"background-size" = true }, - .@"background-attachment" => BackgroundProperty{ .@"background-attachment" = true }, - .@"background-origin" => BackgroundProperty{ .@"background-origin" = true }, - .background => BackgroundProperty{ - .@"background-color" = true, - .@"background-image" = true, - .@"background-position-x" = true, - .@"background-position-y" = true, - .@"background-repeat" = true, - .@"background-size" = true, - .@"background-attachment" = true, - .@"background-origin" = true, - .@"background-clip" = true, - }, + .@"background-color" => @"background-color", + .@"background-image" => @"background-image", + .@"background-position-x" => @"background-position-x", + .@"background-position-y" => @"background-position-y", + .@"background-position" => @"background-position", + .@"background-repeat" => @"background-repeat", + .@"background-size" => @"background-size", + .@"background-attachment" => @"background-attachment", + .@"background-origin" => @"background-origin", + .background => background, else => null, }; } @@ -726,7 +717,7 @@ pub const BackgroundHandler = struct { this.flush(allocator, dest, context); var unparsed = val.deepClone(allocator); context.addUnparsedFallbacks(&unparsed); - if (BackgroundProperty.fromPropertyId(val.property_id)) |prop| { + if (BackgroundProperty.tryFromPropertyId(val.property_id)) |prop| { this.flushed_properties.insert(prop); } diff --git a/src/css/properties/border.zig b/src/css/properties/border.zig index 26120ab545da19..71a2137065c265 100644 --- a/src/css/properties/border.zig +++ b/src/css/properties/border.zig @@ -158,7 +158,7 @@ pub fn GenericBorder(comptime S: type, comptime P: u8) type { } pub fn eql(this: *const This, other: *const This) bool { - return this.width.eql(&other.width) and this.style.eql(&other.style) and this.color.eql(&other.color); + return css.implementEql(@This(), this, other); } pub inline fn default() This { @@ -237,24 +237,7 @@ pub const BorderSideWidth = union(enum) { pub fn deinit(_: *@This(), _: std.mem.Allocator) void {} pub fn eql(this: *const @This(), other: *const @This()) bool { - return switch (this.*) { - .thin => switch (other.*) { - .thin => true, - else => false, - }, - .medium => switch (other.*) { - .medium => true, - else => false, - }, - .thick => switch (other.*) { - .thick => true, - else => false, - }, - .length => switch (other.*) { - .length => this.length.eql(&other.length), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } }; @@ -568,79 +551,79 @@ const BorderShorthand = struct { }; const BorderProperty = packed struct(u32) { - @"border-top-color": bool = false, - @"border-bottom-color": bool = false, - @"border-left-color": bool = false, - @"border-right-color": bool = false, - @"border-block-start-color": bool = false, - @"border-block-end-color": bool = false, - @"border-inline-start-color": bool = false, - @"border-inline-end-color": bool = false, - @"border-top-width": bool = false, - @"border-bottom-width": bool = false, - @"border-left-width": bool = false, - @"border-right-width": bool = false, - @"border-block-start-width": bool = false, - @"border-block-end-width": bool = false, - @"border-inline-start-width": bool = false, - @"border-inline-end-width": bool = false, - @"border-top-style": bool = false, - @"border-bottom-style": bool = false, - @"border-left-style": bool = false, - @"border-right-style": bool = false, - @"border-block-start-style": bool = false, - @"border-block-end-style": bool = false, - @"border-inline-start-style": bool = false, - @"border-inline-end-style": bool = false, + @"top-color": bool = false, + @"bottom-color": bool = false, + @"left-color": bool = false, + @"right-color": bool = false, + @"block-start-color": bool = false, + @"block-end-color": bool = false, + @"inline-start-color": bool = false, + @"inline-end-color": bool = false, + @"top-width": bool = false, + @"bottom-width": bool = false, + @"left-width": bool = false, + @"right-width": bool = false, + @"block-start-width": bool = false, + @"block-end-width": bool = false, + @"inline-start-width": bool = false, + @"inline-end-width": bool = false, + @"top-style": bool = false, + @"bottom-style": bool = false, + @"left-style": bool = false, + @"right-style": bool = false, + @"block-start-style": bool = false, + @"block-end-style": bool = false, + @"inline-start-style": bool = false, + @"inline-end-style": bool = false, __unused: u8 = 0, pub usingnamespace css.Bitflags(@This()); - const @"border-top-color" = BorderProperty{ .@"border-top-color" = true }; - const @"border-bottom-color" = BorderProperty{ .@"border-bottom-color" = true }; - const @"border-left-color" = BorderProperty{ .@"border-left-color" = true }; - const @"border-right-color" = BorderProperty{ .@"border-right-color" = true }; - const @"border-block-start-color" = BorderProperty{ .@"border-block-start-color" = true }; - const @"border-block-end-color" = BorderProperty{ .@"border-block-end-color" = true }; - const @"border-inline-start-color" = BorderProperty{ .@"border-inline-start-color" = true }; - const @"border-inline-end-color" = BorderProperty{ .@"border-inline-end-color" = true }; - const @"border-top-width" = BorderProperty{ .@"border-top-width" = true }; - const @"border-bottom-width" = BorderProperty{ .@"border-bottom-width" = true }; - const @"border-left-width" = BorderProperty{ .@"border-left-width" = true }; - const @"border-right-width" = BorderProperty{ .@"border-right-width" = true }; - const @"border-block-start-width" = BorderProperty{ .@"border-block-start-width" = true }; - const @"border-block-end-width" = BorderProperty{ .@"border-block-end-width" = true }; - const @"border-inline-start-width" = BorderProperty{ .@"border-inline-start-width" = true }; - const @"border-inline-end-width" = BorderProperty{ .@"border-inline-end-width" = true }; - const @"border-top-style" = BorderProperty{ .@"border-top-style" = true }; - const @"border-bottom-style" = BorderProperty{ .@"border-bottom-style" = true }; - const @"border-left-style" = BorderProperty{ .@"border-left-style" = true }; - const @"border-right-style" = BorderProperty{ .@"border-right-style" = true }; - const @"border-block-start-style" = BorderProperty{ .@"border-block-start-style" = true }; - const @"border-block-end-style" = BorderProperty{ .@"border-block-end-style" = true }; - const @"border-inline-start-style" = BorderProperty{ .@"border-inline-start-style" = true }; - const @"border-inline-end-style" = BorderProperty{ .@"border-inline-end-style" = true }; - - const @"border-block-color" = BorderProperty{ .@"border-block-start-color" = true, .@"border-block-end-color" = true }; - const @"border-inline-color" = BorderProperty{ .@"border-inline-start-color" = true, .@"border-inline-end-color" = true }; - const @"border-block-width" = BorderProperty{ .@"border-block-start-width" = true, .@"border-block-end-width" = true }; - const @"border-inline-width" = BorderProperty{ .@"border-inline-start-width" = true, .@"border-inline-end-width" = true }; - const @"border-block-style" = BorderProperty{ .@"border-block-start-style" = true, .@"border-block-end-style" = true }; - const @"border-inline-style" = BorderProperty{ .@"border-inline-start-style" = true, .@"border-inline-end-style" = true }; - const @"border-top" = BorderProperty{ .@"border-top-color" = true, .@"border-top-width" = true, .@"border-top-style" = true }; - const @"border-bottom" = BorderProperty{ .@"border-bottom-color" = true, .@"border-bottom-width" = true, .@"border-bottom-style" = true }; - const @"border-left" = BorderProperty{ .@"border-left-color" = true, .@"border-left-width" = true, .@"border-left-style" = true }; - const @"border-right" = BorderProperty{ .@"border-right-color" = true, .@"border-right-width" = true, .@"border-right-style" = true }; - const @"border-block-start" = BorderProperty{ .@"border-block-start-color" = true, .@"border-block-start-width" = true, .@"border-block-start-style" = true }; - const @"border-block-end" = BorderProperty{ .@"border-block-end-color" = true, .@"border-block-end-width" = true, .@"border-block-end-style" = true }; - const @"border-inline-start" = BorderProperty{ .@"border-inline-start-color" = true, .@"border-inline-start-width" = true, .@"border-inline-start-style" = true }; - const @"border-inline-end" = BorderProperty{ .@"border-inline-end-color" = true, .@"border-inline-end-width" = true, .@"border-inline-end-style" = true }; - const @"border-block" = BorderProperty{ .@"border-block-start-color" = true, .@"border-block-end-color" = true, .@"border-block-start-width" = true, .@"border-block-end-width" = true, .@"border-block-start-style" = true, .@"border-block-end-style" = true }; - const @"border-inline" = BorderProperty{ .@"border-inline-start-color" = true, .@"border-inline-end-color" = true, .@"border-inline-start-width" = true, .@"border-inline-end-width" = true, .@"border-inline-start-style" = true, .@"border-inline-end-style" = true }; - const @"border-width" = BorderProperty{ .@"border-left-width" = true, .@"border-right-width" = true, .@"border-top-width" = true, .@"border-bottom-width" = true }; - const @"border-style" = BorderProperty{ .@"border-left-style" = true, .@"border-right-style" = true, .@"border-top-style" = true, .@"border-bottom-style" = true }; - const @"border-color" = BorderProperty{ .@"border-left-color" = true, .@"border-right-color" = true, .@"border-top-color" = true, .@"border-bottom-color" = true }; - const border = BorderProperty{ .@"border-left-width" = true, .@"border-right-width" = true, .@"border-top-width" = true, .@"border-bottom-width" = true, .@"border-left-style" = true, .@"border-right-style" = true, .@"border-top-style" = true, .@"border-bottom-style" = true, .@"border-left-color" = true, .@"border-right-color" = true, .@"border-top-color" = true, .@"border-bottom-color" = true }; + const @"border-top-color" = BorderProperty{ .@"top-color" = true }; + const @"border-bottom-color" = BorderProperty{ .@"bottom-color" = true }; + const @"border-left-color" = BorderProperty{ .@"left-color" = true }; + const @"border-right-color" = BorderProperty{ .@"right-color" = true }; + const @"border-block-start-color" = BorderProperty{ .@"block-start-color" = true }; + const @"border-block-end-color" = BorderProperty{ .@"block-end-color" = true }; + const @"border-inline-start-color" = BorderProperty{ .@"inline-start-color" = true }; + const @"border-inline-end-color" = BorderProperty{ .@"inline-end-color" = true }; + const @"border-top-width" = BorderProperty{ .@"top-width" = true }; + const @"border-bottom-width" = BorderProperty{ .@"bottom-width" = true }; + const @"border-left-width" = BorderProperty{ .@"left-width" = true }; + const @"border-right-width" = BorderProperty{ .@"right-width" = true }; + const @"border-block-start-width" = BorderProperty{ .@"block-start-width" = true }; + const @"border-block-end-width" = BorderProperty{ .@"block-end-width" = true }; + const @"border-inline-start-width" = BorderProperty{ .@"inline-start-width" = true }; + const @"border-inline-end-width" = BorderProperty{ .@"inline-end-width" = true }; + const @"border-top-style" = BorderProperty{ .@"top-style" = true }; + const @"border-bottom-style" = BorderProperty{ .@"bottom-style" = true }; + const @"border-left-style" = BorderProperty{ .@"left-style" = true }; + const @"border-right-style" = BorderProperty{ .@"right-style" = true }; + const @"border-block-start-style" = BorderProperty{ .@"block-start-style" = true }; + const @"border-block-end-style" = BorderProperty{ .@"block-end-style" = true }; + const @"border-inline-start-style" = BorderProperty{ .@"inline-start-style" = true }; + const @"border-inline-end-style" = BorderProperty{ .@"inline-end-style" = true }; + + const @"border-block-color" = BorderProperty{ .@"block-start-color" = true, .@"block-end-color" = true }; + const @"border-inline-color" = BorderProperty{ .@"inline-start-color" = true, .@"inline-end-color" = true }; + const @"border-block-width" = BorderProperty{ .@"block-start-width" = true, .@"block-end-width" = true }; + const @"border-inline-width" = BorderProperty{ .@"inline-start-width" = true, .@"inline-end-width" = true }; + const @"border-block-style" = BorderProperty{ .@"block-start-style" = true, .@"block-end-style" = true }; + const @"border-inline-style" = BorderProperty{ .@"inline-start-style" = true, .@"inline-end-style" = true }; + const @"border-top" = BorderProperty{ .@"top-color" = true, .@"top-width" = true, .@"top-style" = true }; + const @"border-bottom" = BorderProperty{ .@"bottom-color" = true, .@"bottom-width" = true, .@"bottom-style" = true }; + const @"border-left" = BorderProperty{ .@"left-color" = true, .@"left-width" = true, .@"left-style" = true }; + const @"border-right" = BorderProperty{ .@"right-color" = true, .@"right-width" = true, .@"right-style" = true }; + const @"border-block-start" = BorderProperty{ .@"block-start-color" = true, .@"block-start-width" = true, .@"block-start-style" = true }; + const @"border-block-end" = BorderProperty{ .@"block-end-color" = true, .@"block-end-width" = true, .@"block-end-style" = true }; + const @"border-inline-start" = BorderProperty{ .@"inline-start-color" = true, .@"inline-start-width" = true, .@"inline-start-style" = true }; + const @"border-inline-end" = BorderProperty{ .@"inline-end-color" = true, .@"inline-end-width" = true, .@"inline-end-style" = true }; + const @"border-block" = BorderProperty{ .@"block-start-color" = true, .@"block-end-color" = true, .@"block-start-width" = true, .@"block-end-width" = true, .@"block-start-style" = true, .@"block-end-style" = true }; + const @"border-inline" = BorderProperty{ .@"inline-start-color" = true, .@"inline-end-color" = true, .@"inline-start-width" = true, .@"inline-end-width" = true, .@"inline-start-style" = true, .@"inline-end-style" = true }; + const @"border-width" = BorderProperty{ .@"left-width" = true, .@"right-width" = true, .@"top-width" = true, .@"bottom-width" = true }; + const @"border-style" = BorderProperty{ .@"left-style" = true, .@"right-style" = true, .@"top-style" = true, .@"bottom-style" = true }; + const @"border-color" = BorderProperty{ .@"left-color" = true, .@"right-color" = true, .@"top-color" = true, .@"bottom-color" = true }; + const border = BorderProperty{ .@"left-width" = true, .@"right-width" = true, .@"top-width" = true, .@"bottom-width" = true, .@"left-style" = true, .@"right-style" = true, .@"top-style" = true, .@"bottom-style" = true, .@"left-color" = true, .@"right-color" = true, .@"top-color" = true, .@"bottom-color" = true }; pub fn tryFromPropertyId(property_id: css.PropertyIdTag) ?@This() { @setEvalBranchQuota(10000); @@ -1016,30 +999,30 @@ pub const BorderHandler = struct { comptime block_start_width: []const u8, comptime block_start_style: []const u8, comptime block_start_color: []const u8, - block_start: anytype, + block_start: *BorderShorthand, comptime block_end_prop: []const u8, comptime block_end_width: []const u8, comptime block_end_style: []const u8, comptime block_end_color: []const u8, - block_end: anytype, + block_end: *BorderShorthand, comptime inline_start_prop: []const u8, comptime inline_start_width: []const u8, comptime inline_start_style: []const u8, comptime inline_start_color: []const u8, - inline_start: anytype, + inline_start: *BorderShorthand, comptime inline_end_prop: []const u8, comptime inline_end_width: []const u8, comptime inline_end_style: []const u8, comptime inline_end_color: []const u8, - inline_end: anytype, + inline_end: *BorderShorthand, comptime is_logical: bool, ) void { const State = struct { f: *FlushContext, - block_start: @TypeOf(block_start), - block_end: @TypeOf(block_end), - inline_start: @TypeOf(inline_start), - inline_end: @TypeOf(inline_end), + block_start: *BorderShorthand, + block_end: *BorderShorthand, + inline_start: *BorderShorthand, + inline_end: *BorderShorthand, inline fn shorthand(s: *@This(), comptime p: type, comptime prop_name: []const u8, comptime key: []const u8) void { const has_prop = @field(s.block_start, key) != null and @field(s.block_end, key) != null and @field(s.inline_start, key) != null and @field(s.inline_end, key) != null; diff --git a/src/css/properties/border_image.zig b/src/css/properties/border_image.zig index 5054509d40c4c5..e47112e513714e 100644 --- a/src/css/properties/border_image.zig +++ b/src/css/properties/border_image.zig @@ -40,7 +40,7 @@ pub const BorderImage = struct { /// How the border image is scaled and tiled. repeat: BorderImageRepeat, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"border-image"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"border-image", PropertyFieldMap); pub const PropertyFieldMap = .{ .source = css.PropertyIdTag.@"border-image-source", @@ -188,9 +188,7 @@ pub const BorderImage = struct { var res = css.SmallList(BorderImage, 6).initCapacity(allocator, fallbacks.len()); res.setLen(fallbacks.len()); for (fallbacks.slice(), res.slice_mut()) |fallback, *out| { - out.* = this.*; - out.source = Image.default(); - out.* = out.deepClone(allocator); + out.* = this.deepClone(allocator); out.source = fallback; } @@ -395,33 +393,33 @@ pub const BorderImageSlice = struct { }; pub const BorderImageProperty = packed struct(u8) { - @"border-image-source": bool = false, - @"border-image-slice": bool = false, - @"border-image-width": bool = false, - @"border-image-outset": bool = false, - @"border-image-repeat": bool = false, + source: bool = false, + slice: bool = false, + width: bool = false, + outset: bool = false, + repeat: bool = false, __unused: u3 = 0, - pub const @"border-image-source" = BorderImageProperty{ .@"border-image-source" = true }; - pub const @"border-image-slice" = BorderImageProperty{ .@"border-image-slice" = true }; - pub const @"border-image-width" = BorderImageProperty{ .@"border-image-width" = true }; - pub const @"border-image-outset" = BorderImageProperty{ .@"border-image-outset" = true }; - pub const @"border-image-repeat" = BorderImageProperty{ .@"border-image-repeat" = true }; + pub const @"border-image-source" = BorderImageProperty{ .source = true }; + pub const @"border-image-slice" = BorderImageProperty{ .slice = true }; + pub const @"border-image-width" = BorderImageProperty{ .width = true }; + pub const @"border-image-outset" = BorderImageProperty{ .outset = true }; + pub const @"border-image-repeat" = BorderImageProperty{ .repeat = true }; pub usingnamespace css.Bitflags(@This()); pub const @"border-image" = BorderImageProperty{ - .@"border-image-source" = true, - .@"border-image-slice" = true, - .@"border-image-width" = true, - .@"border-image-outset" = true, - .@"border-image-repeat" = true, + .source = true, + .slice = true, + .width = true, + .outset = true, + .repeat = true, }; pub fn tryFromPropertyId(property_id: css.PropertyIdTag) ?BorderImageProperty { inline for (std.meta.fields(BorderImageProperty)) |field| { if (comptime std.mem.eql(u8, field.name, "__unused")) continue; - const desired = comptime @field(css.PropertyIdTag, field.name); + const desired = comptime @field(css.PropertyIdTag, "border-image-" ++ field.name); if (desired == property_id) { var result: BorderImageProperty = .{}; @field(result, field.name) = true; @@ -601,7 +599,7 @@ pub const BorderImageHandler = struct { this.flushed_properties.insert(BorderImageProperty.@"border-image"); } else { if (source) |*mut_source| { - if (!this.flushed_properties.contains(BorderImageProperty{ .@"border-image-source" = true })) { + if (!this.flushed_properties.contains(BorderImageProperty.@"border-image-source")) { for (mut_source.getFallbacks(allocator, context.targets).slice()) |fallback| { dest.append(allocator, Property{ .@"border-image-source" = fallback }) catch bun.outOfMemory(); } diff --git a/src/css/properties/border_radius.zig b/src/css/properties/border_radius.zig index d2c9843c24309b..ec35e73618d1f0 100644 --- a/src/css/properties/border_radius.zig +++ b/src/css/properties/border_radius.zig @@ -38,7 +38,7 @@ pub const BorderRadius = struct { /// The x and y radius values for the bottom left corner. bottom_left: Size2D(LengthPercentage), - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"border-radius"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"border-radius", PropertyFieldMap); pub const PropertyFieldMap = .{ .top_left = "border-top-left-radius", diff --git a/src/css/properties/box_shadow.zig b/src/css/properties/box_shadow.zig index dea6c1bf535f01..472ca82ee87ab3 100644 --- a/src/css/properties/box_shadow.zig +++ b/src/css/properties/box_shadow.zig @@ -19,10 +19,15 @@ const DashedIdent = css.css_values.ident.DashedIdent; const Image = css.css_values.image.Image; const CssColor = css.css_values.color.CssColor; const Ratio = css.css_values.ratio.Ratio; -const Length = css.css_values.length.LengthValue; +const Length = css.css_values.length.Length; const Rect = css.css_values.rect.Rect; const NumberOrPercentage = css.css_values.percentage.NumberOrPercentage; +const VendorPrefix = css.VendorPrefix; +const Property = css.Property; +const PropertyId = css.PropertyId; +const Feature = css.prefixes.Feature; + /// A value for the [box-shadow](https://drafts.csswg.org/css-backgrounds/#box-shadow) property. pub const BoxShadow = struct { /// The color of the box shadow. @@ -128,4 +133,140 @@ pub const BoxShadow = struct { pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { return css.implementEql(@This(), lhs, rhs); } + + pub fn isCompatible(this: *const @This(), browsers: css.targets.Browsers) bool { + return this.color.isCompatible(browsers) and + this.x_offset.isCompatible(browsers) and + this.y_offset.isCompatible(browsers) and + this.blur.isCompatible(browsers) and + this.spread.isCompatible(browsers); + } +}; + +pub const BoxShadowHandler = struct { + box_shadows: ?struct { SmallList(BoxShadow, 1), VendorPrefix } = null, + flushed: bool = false, + + pub fn handleProperty(this: *@This(), property: *const Property, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) bool { + switch (property.*) { + .@"box-shadow" => |*b| { + const box_shadows: *const SmallList(BoxShadow, 1) = &b.*[0]; + const prefix: VendorPrefix = b.*[1]; + if (this.box_shadows != null and context.targets.browsers != null and !box_shadows.isCompatible(context.targets.browsers.?)) { + this.flush(dest, context); + } + + if (this.box_shadows) |*bxs| { + const val: *SmallList(BoxShadow, 1) = &bxs.*[0]; + const prefixes: *VendorPrefix = &bxs.*[1]; + if (!val.eql(box_shadows) and !prefixes.contains(prefix)) { + this.flush(dest, context); + this.box_shadows = .{ + box_shadows.deepClone(context.allocator), + prefix, + }; + } else { + val.* = box_shadows.deepClone(context.allocator); + prefixes.insert(prefix); + } + } else { + this.box_shadows = .{ + box_shadows.deepClone(context.allocator), + prefix, + }; + } + }, + .unparsed => |unp| { + if (unp.property_id == .@"box-shadow") { + this.flush(dest, context); + + var unparsed = unp.deepClone(context.allocator); + context.addUnparsedFallbacks(&unparsed); + dest.append(context.allocator, .{ .unparsed = unparsed }) catch bun.outOfMemory(); + this.flushed = true; + } else return false; + }, + else => return false, + } + + return true; + } + + pub fn finalize(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + this.flush(dest, context); + this.flushed = false; + } + + pub fn flush(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + if (this.box_shadows == null) return; + + const box_shadows: SmallList(BoxShadow, 1), const prefixes2: VendorPrefix = bun.take(&this.box_shadows) orelse { + this.flushed = true; + return; + }; + + if (!this.flushed) { + const ColorFallbackKind = css.ColorFallbackKind; + var prefixes = context.targets.prefixes(prefixes2, Feature.box_shadow); + var fallbacks = ColorFallbackKind.empty(); + for (box_shadows.slice()) |*shadow| { + fallbacks.insert(shadow.color.getNecessaryFallbacks(context.targets)); + } + + if (fallbacks.contains(ColorFallbackKind{ .rgb = true })) { + var rgb = SmallList(BoxShadow, 1).initCapacity(context.allocator, box_shadows.len()); + rgb.setLen(box_shadows.len()); + for (box_shadows.slice(), rgb.slice_mut()) |*input, *output| { + output.color = input.color.toRGB(context.allocator) orelse input.color.deepClone(context.allocator); + const fields = std.meta.fields(BoxShadow); + inline for (fields) |field| { + if (comptime std.mem.eql(u8, field.name, "color")) continue; + @field(output, field.name) = css.generic.deepClone(field.type, &@field(input, field.name), context.allocator); + } + } + + dest.append(context.allocator, .{ .@"box-shadow" = .{ rgb, prefixes } }) catch bun.outOfMemory(); + if (prefixes.contains(VendorPrefix.NONE)) { + prefixes = VendorPrefix.NONE; + } else { + // Only output RGB for prefixed property (e.g. -webkit-box-shadow) + return; + } + } + + if (fallbacks.contains(ColorFallbackKind.P3)) { + var p3 = SmallList(BoxShadow, 1).initCapacity(context.allocator, box_shadows.len()); + p3.setLen(box_shadows.len()); + for (box_shadows.slice(), p3.slice_mut()) |*input, *output| { + output.color = input.color.toP3(context.allocator) orelse input.color.deepClone(context.allocator); + const fields = std.meta.fields(BoxShadow); + inline for (fields) |field| { + if (comptime std.mem.eql(u8, field.name, "color")) continue; + @field(output, field.name) = css.generic.deepClone(field.type, &@field(input, field.name), context.allocator); + } + } + dest.append(context.allocator, .{ .@"box-shadow" = .{ p3, VendorPrefix.NONE } }) catch bun.outOfMemory(); + } + + if (fallbacks.contains(ColorFallbackKind.LAB)) { + var lab = SmallList(BoxShadow, 1).initCapacity(context.allocator, box_shadows.len()); + lab.setLen(box_shadows.len()); + for (box_shadows.slice(), lab.slice_mut()) |*input, *output| { + output.color = input.color.toLAB(context.allocator) orelse input.color.deepClone(context.allocator); + const fields = std.meta.fields(BoxShadow); + inline for (fields) |field| { + if (comptime std.mem.eql(u8, field.name, "color")) continue; + @field(output, field.name) = css.generic.deepClone(field.type, &@field(input, field.name), context.allocator); + } + } + dest.append(context.allocator, .{ .@"box-shadow" = .{ lab, VendorPrefix.NONE } }) catch bun.outOfMemory(); + } else { + dest.append(context.allocator, .{ .@"box-shadow" = .{ box_shadows, prefixes } }) catch bun.outOfMemory(); + } + } else { + dest.append(context.allocator, .{ .@"box-shadow" = .{ box_shadows, prefixes2 } }) catch bun.outOfMemory(); + } + + this.flushed = true; + } }; diff --git a/src/css/properties/custom.zig b/src/css/properties/custom.zig index c94ed570fdd6d7..29ac1c3f87a85d 100644 --- a/src/css/properties/custom.zig +++ b/src/css/properties/custom.zig @@ -462,9 +462,9 @@ pub const TokenList = struct { } continue; }, - .hash, .idhash => { + .unrestrictedhash, .idhash => { const h = switch (tok.*) { - .hash => |h| h, + .unrestrictedhash => |h| h, .idhash => |h| h, else => unreachable, }; @@ -472,7 +472,7 @@ pub const TokenList = struct { const r, const g, const b, const a = css.color.parseHashColor(h) orelse { tokens.append( input.allocator(), - .{ .token = .{ .hash = h } }, + .{ .token = .{ .unrestrictedhash = h } }, ) catch unreachable; break :brk; }; @@ -859,13 +859,12 @@ pub const UnresolvedColor = union(enum) { const dark: *const TokenList = &ld.dark; if (!dest.targets.isCompatible(.light_dark)) { - // TODO(zack): lightningcss -> buncss - try dest.writeStr("var(--lightningcss-light)"); + try dest.writeStr("var(--buncss-light"); try dest.delim(',', false); try light.toCss(W, dest, is_custom_property); try dest.writeChar(')'); try dest.whitespace(); - try dest.writeStr("var(--lightningcss-dark"); + try dest.writeStr("var(--buncss-dark"); try dest.delim(',', false); try dark.toCss(W, dest, is_custom_property); return dest.writeChar(')'); diff --git a/src/css/properties/display.zig b/src/css/properties/display.zig index eba2fee7cdf464..3671d346fe556a 100644 --- a/src/css/properties/display.zig +++ b/src/css/properties/display.zig @@ -241,14 +241,14 @@ pub const DisplayInside = union(enum) { const displayInsideMap = bun.ComptimeStringMap(DisplayInside, .{ .{ "flow", DisplayInside.flow }, .{ "flow-root", DisplayInside.flow_root }, - .{ "table", .table }, - .{ "flex", .{ .flex = css.VendorPrefix{ .none = true } } }, - .{ "-webkit-flex", .{ .flex = css.VendorPrefix{ .webkit = true } } }, - .{ "-ms-flexbox", .{ .flex = css.VendorPrefix{ .ms = true } } }, - .{ "-webkit-box", .{ .box = css.VendorPrefix{ .webkit = true } } }, - .{ "-moz-box", .{ .box = css.VendorPrefix{ .moz = true } } }, - .{ "grid", .grid }, - .{ "ruby", .ruby }, + .{ "table", DisplayInside.table }, + .{ "flex", DisplayInside{ .flex = css.VendorPrefix{ .none = true } } }, + .{ "-webkit-flex", DisplayInside{ .flex = css.VendorPrefix{ .webkit = true } } }, + .{ "-ms-flexbox", DisplayInside{ .flex = css.VendorPrefix{ .ms = true } } }, + .{ "-webkit-box", DisplayInside{ .box = css.VendorPrefix{ .webkit = true } } }, + .{ "-moz-box", DisplayInside{ .box = css.VendorPrefix{ .moz = true } } }, + .{ "grid", DisplayInside.grid }, + .{ "ruby", DisplayInside.ruby }, }); const location = input.currentSourceLocation(); diff --git a/src/css/properties/flex.zig b/src/css/properties/flex.zig index 5f52f82f209892..c63f7597026dd9 100644 --- a/src/css/properties/flex.zig +++ b/src/css/properties/flex.zig @@ -94,7 +94,7 @@ pub const FlexFlow = struct { /// How the flex items wrap. wrap: FlexWrap, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"flex-flow"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"flex-flow", PropertyFieldMap); pub const PropertyFieldMap = .{ .direction = css.PropertyIdTag.@"flex-direction", @@ -170,7 +170,7 @@ pub const Flex = struct { /// The flex basis. basis: LengthPercentageOrAuto, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.flex); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.flex, PropertyFieldMap); pub const PropertyFieldMap = .{ .grow = css.PropertyIdTag.@"flex-grow", @@ -303,6 +303,8 @@ pub const BoxDirection = enum { pub usingnamespace css.DefineEnumProperty(@This()); }; +pub const FlexAlign = BoxAlign; + /// A value for the legacy (prefixed) [box-align](https://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment) property. /// Equivalent to the `align-items` property in the standard syntax. /// A value for the legacy (prefixed) [box-align](https://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment) property. @@ -320,6 +322,19 @@ pub const BoxAlign = enum { stretch, pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn fromStandard(@"align": *const css.css_properties.@"align".AlignItems) ?BoxAlign { + return switch (@"align".*) { + .self_position => |sp| if (sp.overflow == null) switch (sp.value) { + .start, .@"flex-start" => .start, + .end, .@"flex-end" => .end, + .center => .center, + else => null, + } else null, + .stretch => .stretch, + else => null, + }; + } }; /// A value for the legacy (prefixed) [box-pack](https://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#packing) property. @@ -337,6 +352,21 @@ pub const BoxPack = enum { justify, pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn fromStandard(justify: *const css.css_properties.@"align".JustifyContent) ?BoxPack { + return switch (justify.*) { + .content_distribution => |cd| switch (cd) { + .@"space-between" => .justify, + else => null, + }, + .content_position => |cp| if (cp.overflow == null) switch (cp.value) { + .start, .@"flex-start" => .start, + .end, .@"flex-end" => .end, + .center => .center, + } else null, + else => null, + }; + } }; /// A value for the legacy (prefixed) [box-lines](https://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#multiple) property. @@ -378,6 +408,22 @@ pub const FlexPack = enum { distribute, pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn fromStandard(justify: *const css.css_properties.@"align".JustifyContent) ?FlexPack { + return switch (justify.*) { + .content_distribution => |cd| switch (cd) { + .@"space-between" => .justify, + .@"space-around" => .distribute, + else => null, + }, + .content_position => |cp| if (cp.overflow == null) switch (cp.value) { + .start, .@"flex-start" => .start, + .end, .@"flex-end" => .end, + .center => .center, + } else null, + else => null, + }; + } }; /// A value for the legacy (prefixed) [flex-item-align](https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align) property. @@ -399,6 +445,20 @@ pub const FlexItemAlign = enum { stretch, pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn fromStandard(justify: *const css.css_properties.@"align".AlignSelf) ?FlexItemAlign { + return switch (justify.*) { + .auto => .auto, + .stretch => .stretch, + .self_position => |sp| if (sp.overflow == null) switch (sp.value) { + .start, .@"flex-start" => .start, + .end, .@"flex-end" => .end, + .center => .center, + else => null, + } else null, + else => null, + }; + } }; /// A value for the legacy (prefixed) [flex-line-pack](https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-line-pack) property. @@ -420,6 +480,23 @@ pub const FlexLinePack = enum { stretch, pub usingnamespace css.DefineEnumProperty(@This()); + + pub fn fromStandard(justify: *const css.css_properties.@"align".AlignContent) ?FlexLinePack { + return switch (justify.*) { + .content_distribution => |cd| switch (cd) { + .@"space-between" => .justify, + .@"space-around" => .distribute, + .stretch => .stretch, + else => null, + }, + .content_position => |cp| if (cp.overflow == null) switch (cp.value) { + .start, .@"flex-start" => .start, + .end, .@"flex-end" => .end, + .center => .center, + } else null, + else => null, + }; + } }; pub const BoxOrdinalGroup = CSSInteger; diff --git a/src/css/properties/font.zig b/src/css/properties/font.zig index 80af832a245af5..93935b9228af29 100644 --- a/src/css/properties/font.zig +++ b/src/css/properties/font.zig @@ -608,7 +608,7 @@ pub const Font = struct { /// How the text should be capitalized. Only CSS 2.1 values are supported. variant_caps: FontVariantCaps, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.font); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.font, PropertyFieldMap); pub const PropertyFieldMap = .{ .family = css.PropertyIdTag.@"font-family", diff --git a/src/css/properties/generate_properties.ts b/src/css/properties/generate_properties.ts index f34bd3060d8717..2dbe7defa422cf 100644 --- a/src/css/properties/generate_properties.ts +++ b/src/css/properties/generate_properties.ts @@ -437,6 +437,21 @@ function generatePropertyIdImpl(property_defs: Record): str const tag = @intFromEnum(this.*); hasher.update(std.mem.asBytes(&tag)); } + + pub fn setPrefixesForTargets(this: *PropertyId, targets: Targets) void { + switch (this.*) { + ${Object.entries(property_defs) + .map(([name, meta]) => { + if (meta.unprefixed === false || meta.valid_prefixes === undefined) return `.${escapeIdent(name)} => {},`; + return `.${escapeIdent(name)} => |*x| { + x.* = targets.prefixes(x.*, Feature.${featureName(name)}); + }, + `; + }) + .join("\n")} + else => {}, + } + } `; } @@ -1274,27 +1289,27 @@ generateCode({ // "font-palette": { // ty: "DashedIdentReference", // }, - // "transition-property": { - // ty: "SmallList(PropertyId, 1)", - // valid_prefixes: ["webkit", "moz", "ms"], - // }, - // "transition-duration": { - // ty: "SmallList(Time, 1)", - // valid_prefixes: ["webkit", "moz", "ms"], - // }, - // "transition-delay": { - // ty: "SmallList(Time, 1)", - // valid_prefixes: ["webkit", "moz", "ms"], - // }, - // "transition-timing-function": { - // ty: "SmallList(EasingFunction, 1)", - // valid_prefixes: ["webkit", "moz", "ms"], - // }, - // transition: { - // ty: "SmallList(Transition, 1)", - // valid_prefixes: ["webkit", "moz", "ms"], - // shorthand: true, - // }, + "transition-property": { + ty: "SmallList(PropertyId, 1)", + valid_prefixes: ["webkit", "moz", "ms"], + }, + "transition-duration": { + ty: "SmallList(Time, 1)", + valid_prefixes: ["webkit", "moz", "ms"], + }, + "transition-delay": { + ty: "SmallList(Time, 1)", + valid_prefixes: ["webkit", "moz", "ms"], + }, + "transition-timing-function": { + ty: "SmallList(EasingFunction, 1)", + valid_prefixes: ["webkit", "moz", "ms"], + }, + transition: { + ty: "SmallList(Transition, 1)", + valid_prefixes: ["webkit", "moz", "ms"], + shorthand: true, + }, // "animation-name": { // ty: "AnimationNameList", // valid_prefixes: ["webkit", "moz", "o"], @@ -1347,42 +1362,42 @@ generateCode({ // valid_prefixes: ["webkit", "moz", "o"], // shorthand: true, // }, - // transform: { - // ty: "TransformList", - // valid_prefixes: ["webkit", "moz", "ms", "o"], - // }, - // "transform-origin": { - // ty: "Position", - // valid_prefixes: ["webkit", "moz", "ms", "o"], - // }, - // "transform-style": { - // ty: "TransformStyle", - // valid_prefixes: ["webkit", "moz"], - // }, - // "transform-box": { - // ty: "TransformBox", - // }, - // "backface-visibility": { - // ty: "BackfaceVisibility", - // valid_prefixes: ["webkit", "moz"], - // }, - // perspective: { - // ty: "Perspective", - // valid_prefixes: ["webkit", "moz"], - // }, - // "perspective-origin": { - // ty: "Position", - // valid_prefixes: ["webkit", "moz"], - // }, - // translate: { - // ty: "Translate", - // }, - // rotate: { - // ty: "Rotate", - // }, - // scale: { - // ty: "Scale", - // }, + transform: { + ty: "TransformList", + valid_prefixes: ["webkit", "moz", "ms", "o"], + }, + "transform-origin": { + ty: "Position", + valid_prefixes: ["webkit", "moz", "ms", "o"], + }, + "transform-style": { + ty: "TransformStyle", + valid_prefixes: ["webkit", "moz"], + }, + "transform-box": { + ty: "TransformBox", + }, + "backface-visibility": { + ty: "BackfaceVisibility", + valid_prefixes: ["webkit", "moz"], + }, + perspective: { + ty: "Perspective", + valid_prefixes: ["webkit", "moz"], + }, + "perspective-origin": { + ty: "Position", + valid_prefixes: ["webkit", "moz"], + }, + translate: { + ty: "Translate", + }, + rotate: { + ty: "Rotate", + }, + scale: { + ty: "Scale", + }, // "text-transform": { // ty: "TextTransform", // }, @@ -1674,6 +1689,7 @@ generateCode({ ty: "MaskBorder", shorthand: true, }, + // WebKit additions "-webkit-mask-composite": { ty: "SmallList(WebKitMaskComposite, 1)", }, @@ -1712,6 +1728,7 @@ generateCode({ valid_prefixes: ["webkit"], unprefixed: false, }, + // TODO: Hello future Zack, if you uncomment this, remember to uncomment the corresponding value in FallbackHandler in prefix_handler.zig :) // filter: { // ty: "FilterList", @@ -1738,9 +1755,9 @@ generateCode({ // "view-transition-name": { // ty: "CustomIdent", // }, - // "color-scheme": { - // ty: "ColorScheme", - // }, + "color-scheme": { + ty: "ColorScheme", + }, }); function prelude() { @@ -1761,6 +1778,19 @@ const PropertyIdImpl = @import("./properties_impl.zig").PropertyIdImpl; const CSSWideKeyword = css.css_properties.CSSWideKeyword; const UnparsedProperty = css.css_properties.custom.UnparsedProperty; const CustomProperty = css.css_properties.custom.CustomProperty; +const Targets = css.targets.Targets; +const Feature = css.prefixes.Feature; + +const ColorScheme = css.css_properties.ui.ColorScheme; + +const TransformList = css.css_properties.transform.TransformList; +const TransformStyle = css.css_properties.transform.TransformStyle; +const TransformBox = css.css_properties.transform.TransformBox; +const BackfaceVisibility = css.css_properties.transform.BackfaceVisibility; +const Perspective = css.css_properties.transform.Perspective; +const Translate = css.css_properties.transform.Translate; +const Rotate = css.css_properties.transform.Rotate; +const Scale = css.css_properties.transform.Scale; const css_values = css.css_values; const CssColor = css.css_values.color.CssColor; @@ -1893,7 +1923,7 @@ const FontVariantCaps = font.FontVariantCaps; const LineHeight = font.LineHeight; const Font = font.Font; // const VerticalAlign = font.VerticalAlign; -// const Transition = transition.Transition; +const Transition = transition.Transition; // const AnimationNameList = animation.AnimationNameList; // const AnimationList = animation.AnimationList; // const AnimationIterationCount = animation.AnimationIterationCount; @@ -1994,3 +2024,7 @@ const SmallList = css.SmallList; `; } + +function featureName(name: string): string { + return name.replaceAll("-", "_"); +} diff --git a/src/css/properties/grid.zig b/src/css/properties/grid.zig new file mode 100644 index 00000000000000..a4b2d60773bbb9 --- /dev/null +++ b/src/css/properties/grid.zig @@ -0,0 +1,561 @@ +const std = @import("std"); +const bun = @import("root").bun; +const Allocator = std.mem.Allocator; +const ArrayList = std.ArrayListUnmanaged; + +pub const css = @import("../css_parser.zig"); + +const SmallList = css.SmallList; +const Printer = css.Printer; +const PrintErr = css.PrintErr; +const Error = css.Error; + +const Property = css.Property; +const PropertyId = css.PropertyId; + +const ContainerName = css.css_rules.container.ContainerName; + +const CSSNumberFns = css.css_values.number.CSSNumberFns; +const LengthPercentage = css.css_values.length.LengthPercentage; +const CustomIdent = css.css_values.ident.CustomIdent; +const CSSString = css.css_values.string.CSSString; +const CSSNumber = css.css_values.number.CSSNumber; +const LengthPercentageOrAuto = css.css_values.length.LengthPercentageOrAuto; +const Size2D = css.css_values.size.Size2D; +const DashedIdent = css.css_values.ident.DashedIdent; +const Image = css.css_values.image.Image; +const CssColor = css.css_values.color.CssColor; +const Ratio = css.css_values.ratio.Ratio; +const Length = css.css_values.length.LengthValue; +const Rect = css.css_values.rect.Rect; +const NumberOrPercentage = css.css_values.percentage.NumberOrPercentage; +const CustomIdentList = css.css_values.ident.CustomIdentList; +const Angle = css.css_values.angle.Angle; +const Url = css.css_values.url.Url; +const CSSInteger = css.css_values.number.CSSInteger; +const BabyList = bun.BabyList; + +const isFlex2009 = css.prefixes.Feature.isFlex2009; + +const VendorPrefix = css.VendorPrefix; + +/// A [track sizing](https://drafts.csswg.org/css-grid-2/#track-sizing) value +/// for the `grid-template-rows` and `grid-template-columns` properties. +pub const TrackSizing = union(enum) { + /// No explicit grid tracks. + none, + /// A list of grid tracks. + tracklist: TrackList, + + pub usingnamespace css.DeriveParse(@This()); + pub usingnamespace css.DeriveToCss(@This()); +}; + +/// A [``](https://drafts.csswg.org/css-grid-2/#typedef-track-list) value, +/// as used in the `grid-template-rows` and `grid-template-columns` properties. +/// +/// See [TrackSizing](TrackSizing). +pub const TrackList = struct { + /// A list of line names. + line_names: bun.BabyList(CustomIdentList), + /// A list of grid track items. + items: bun.BabyList(TrackListItem), + + pub fn parse(input: *css.Parser) css.Result(@This()) { + var line_names = BabyList(CustomIdentList){}; + var items = BabyList(TrackListItem){}; + + while (true) { + const line_name = input.tryParse(parseLineNames, .{}).asValue() orelse CustomIdentList{}; + line_names.append(input.allocator(), line_name) catch bun.outOfMemory(); + + if (input.tryParse(TrackSize.parse, .{}).asValue()) |track_size| { + // TODO: error handling + items.append(.{ .track_size = track_size }) catch bun.outOfMemory(); + } else if (input.tryParse(TrackRepeat.parse, .{}).asValue()) |repeat| { + // TODO: error handling + items.append(.{ .track_repeat = repeat }) catch bun.outOfMemory(); + } else { + break; + } + } + + if (items.len == 0) { + return .{ .err = input.newCustomError(.invalid_declaration) }; + } + + return .{ .result = .{ + .line_names = line_names, + .items = items, + } }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) css.PrintErr!void { + var items_index = 0; + var first = true; + + for (this.line_names.sliceConst()) |*names| { + if (!names.isEmpty()) try serializeLineNames(names, W, dest); + + if (items_index < this.items.len) { + const item = this.items.at(items_index); + items_index += 1; + + // Whitespace is required if there are no line names. + if (!names.isEmpty()) { + try dest.whitespace(); + } else if (!first) { + try dest.writeChar(' '); + } + + switch (item.*) { + .track_repeat => |*repeat| try repeat.toCss(W, dest), + .track_size => |*size| try size.toCss(W, dest), + } + } + + first = false; + } + } +}; + +/// Either a track size or `repeat()` function. +/// +/// See [TrackList](TrackList). +pub const TrackListItem = union(enum) { + /// A track size. + track_size: TrackSize, + /// A `repeat()` function. + track_repeat: TrackRepeat, +}; + +/// A [track size](https://drafts.csswg.org/css-grid-2/#typedef-track-size) value. +/// +/// See [TrackList](TrackList). +pub const TrackSize = union(enum) { + /// An explicit track breadth. + track_breadth: TrackBreadth, + /// The `minmax()` function. + min_max: struct { + /// The minimum value. + min: TrackBreadth, + /// The maximum value. + max: TrackBreadth, + }, + /// The `fit-content()` function. + fit_content: LengthPercentage, + + pub fn default() @This() { + return .{ .track_breadth = TrackBreadth.auto }; + } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } + + pub fn parse(input: *css.Parser) css.Result(@This()) { + if (input.tryParse(TrackBreadth.parse, .{}).asValue()) |breadth| { + return .{ .result = .{ .track_breadth = breadth } }; + } + + if (input.tryParse(css.Parser.expectFunctionMatching, .{"minmax"}).isOk()) { + return input.parseNestedBlock(struct { + pub fn parse(i: *css.Parser) css.Result(TrackSize) { + const min = switch (TrackBreadth.parseInternal(i, false)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + if (i.expectComma().asErr()) |e| return .{ .err = e }; + return .{ + .result = .{ .min_max = .{ .min = min, .max = switch (TrackBreadth.parse(i)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + } } }, + }; + } + }.parseFn); + } + + if (input.expectFunctionMatching("fit-content").asErr()) |e| return .{ .err = e }; + + const len = switch (input.parseNestedBlock(css.voidWrap(LengthPercentage, LengthPercentage.parse))) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + + return .{ .result = .{ .fit_content = len } }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) css.PrintErr!void { + switch (this.*) { + .track_breadth => |breadth| try breadth.toCss(W, dest), + .min_max => |mm| { + try dest.writeStr("minmax("); + try mm.min.toCss(W, dest); + try dest.delim(',', false); + try mm.max.toCss(W, dest); + try dest.writeChar(')'); + }, + .fit_content => |len| { + try dest.writeStr("fit-content("); + try len.toCss(W, dest); + try dest.writeChar(')'); + }, + } + } +}; + +pub const TrackSizeList = struct { + v: SmallList(TrackSize, 1) = .{}, + + pub fn parse(input: *css.Parser) css.Result(@This()) { + var res = SmallList(TrackSize, 1){}; + while (input.tryParse(TrackSize.parse, .{}).asValue()) |size| { + res.append(input.allocator(), size) catch bun.outOfMemory(); + } + + if (res.len() == 1 and res.at(0).eql(&TrackSize.default())) { + res.clearRetainingCapacity(); + } + + return .{ .result = .{ .v = res } }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) css.PrintErr!void { + if (this.v.len() == 0) { + try dest.writeStr("auto"); + return; + } + + var first = true; + for (this.v.slice()) |item| { + if (first) { + first = false; + } else { + try dest.writeChar(' '); + } + try item.toCss(W, dest); + } + } +}; + +/// A [track breadth](https://drafts.csswg.org/css-grid-2/#typedef-track-breadth) value. +/// +/// See [TrackSize](TrackSize). +pub const TrackBreadth = union(enum) { + /// An explicit length. + length: LengthPercentage, + /// A flex factor. + flex: CSSNumber, + /// The `min-content` keyword. + min_content, + /// The `max-content` keyword. + max_content, + /// The `auto` keyword. + auto, + + pub fn parse(input: *css.Parser) css.Result(@This()) { + return TrackBreadth.parseInternal(input, true); + } + + fn parseInternal(input: *css.Parser, allow_flex: bool) css.Result(@This()) { + if (input.tryParse(LengthPercentage.parse, .{}).asValue()) |len| { + return .{ .result = .{ .length = len } }; + } + + if (allow_flex) { + if (input.tryParse(TrackBreadth.parseFlex, .{}).asValue()) |flex| { + return .{ .result = .{ .flex = flex } }; + } + } + + const location = input.currentSourceLocation(); + const ident = switch (input.expectIdent()) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + + if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "auto")) { + return .{ .result = .auto }; + } else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "min-content")) { + return .{ .result = .min_content }; + } else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "max-content")) { + return .{ .result = .max_content }; + } + + return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) }; + } + + fn parseFlex(input: *css.Parser) css.Result(CSSNumber) { + const location = input.currentSourceLocation(); + const token = switch (input.next()) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + + if (token == .dimension) { + if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(token.dimension.unit, "fr") and token.dimension.value >= 0.0) { + return .{ .result = token.dimension.value }; + } + } + + return .{ .err = location.newUnexpectedTokenError(token) }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) css.PrintErr!void { + switch (this.*) { + .auto => try dest.writeStr("auto"), + .min_content => try dest.writeStr("min-content"), + .max_content => try dest.writeStr("max-content"), + .length => |len| try len.toCss(W, dest), + // .flex => |flex| try css.CSSNumberFns.serializeDimension(&flex, "fr", W, dest), + .flex => |flex| css.serializer.serializeDimension(flex, "fr", W, dest), + } + } +}; + +/// A `repeat()` function. +/// +/// See [TrackList](TrackList). +pub const TrackRepeat = struct { + /// The repeat count. + count: RepeatCount, + /// The line names to repeat. + line_names: bun.BabyList(CustomIdentList), + /// The track sizes to repeat. + track_sizes: bun.BabyList(TrackSize), + + pub fn parse(input: *css.Parser) css.Result(@This()) { + if (input.expectFunctionMatching("repeat").asErr()) |e| return .{ .err = e }; + + return input.parseNestedBlock(struct { + fn parse(i: *css.Parser) css.Result(TrackRepeat) { + const count = switch (@call(.auto, @field(RepeatCount, "parse"), .{i})) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + + if (i.expectComma().asErr()) |e| return .{ .err = e }; + + var line_names = bun.BabyList(CustomIdentList).init(i.allocator); + var track_sizes = bun.BabyList(TrackSize).init(i.allocator); + + while (true) { + const line_name = i.tryParse(parseLineNames, .{}).unwrapOr(CustomIdentList{}); + line_names.append(i.allocator(), line_name) catch bun.outOfMemory(); + + if (input.tryParse(TrackSize.parse, .{}).asValue()) |track_size| { + // TODO: error handling + track_sizes.append(i.allocator(), track_size) catch bun.outOfMemory(); + } else { + break; + } + } + + return .{ .result = .{ + .count = count, + .line_names = line_names, + .track_sizes = track_sizes, + } }; + } + }.parse); + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *Printer(W)) PrintErr!void { + try dest.writeStr("repeat("); + try this.count.toCss(W, dest); + try dest.delim(',', false); + + var track_sizes_index = 0; + var first = true; + for (this.line_names.sliceConst()) |*names| { + if (!names.isEmpty()) { + try serializeLineNames(names, W, dest); + } + + if (track_sizes_index < this.track_sizes.len) { + const size = this.track_sizes.at(track_sizes_index); + track_sizes_index += 1; + + if (!names.isEmpty()) { + try dest.whitespace(); + } else if (!first) { + try dest.writeChar(' '); + } + try size.toCss(W, dest); + } + + first = false; + } + + try dest.writeChar(')'); + } +}; + +fn serializeLineNames(names: []const CustomIdent, comptime W: type, dest: *Printer(W)) PrintErr!void { + try dest.writeChar('['); + var first = true; + for (names) |*name| { + if (first) { + first = false; + } else { + try dest.writeChar(' '); + } + try writeIdent(&name.value, W, dest); + } + try dest.writeChar(']'); +} + +fn writeIdent(name: []const u8, comptime W: type, dest: *Printer(W)) PrintErr!void { + const css_module_grid_enabled = if (dest.css_module) |*css_module| css_module.config.grid else false; + if (css_module_grid_enabled) { + if (dest.css_module) |*css_module| { + if (css_module.config.pattern.segments.last()) |last| { + if (last != css.css_modules.Segment.local) { + return try dest.addInvalidCssModulesPatternInGridError(); + } + } + } + } + + try dest.writeIdent(name, css_module_grid_enabled); +} + +fn parseLineNames(input: *css.Parser) css.Result(CustomIdentList) { + if (input.expectSquareBracketBlock().asErr()) |e| return .{ .err = e }; + + return input.parseNestedBlock(struct { + fn parse(i: *css.Parser) css.Result(CustomIdentList) { + var values = CustomIdentList{}; + + while (input.tryParse(CustomIdent.parse, .{}).asValue()) |ident| { + values.append(i.allocator(), ident) catch bun.outOfMemory(); + } + + return .{ .result = values }; + } + }.parse); +} + +/// A [``](https://drafts.csswg.org/css-grid-2/#typedef-track-repeat) value, +/// used in the `repeat()` function. +/// +/// See [TrackRepeat](TrackRepeat). +pub const RepeatCount = union(enum) { + /// The number of times to repeat. + number: CSSInteger, + /// The `auto-fill` keyword. + @"auto-fill", + /// The `auto-fit` keyword. + @"auto-fit", + + pub usingnamespace css.DeriveParse(@This()); + pub usingnamespace css.DeriveToCss(@This()); + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } +}; + +/// A grid template areas value. +/// See https://drafts.csswg.org/css-grid-2/#propdef-grid-template-areas +pub const GridTemplateAreas = union(enum) { + /// No named grid areas. + none, + /// Defines the list of named grid areas. + areas: struct { + /// The number of columns in the grid. + columns: u32, + /// A flattened list of grid area names. + /// Unnamed areas specified by the `.` token are represented as null. + areas: SmallList(?[]const u8, 1), + }, + + pub fn parse(input: *css.Parser) css.Result(@This()) { + if (input.tryParse(struct { + fn parse(i: *css.Parser) css.Result(void) { + return i.expectIdentMatching("none"); + } + }.parse, .{}).asValue()) |_| { + return .{ .result = .none }; + } + + var tokens = SmallList(?[]const u8, 1){}; + var row: u32 = 0; + var columns: u32 = 0; + + if (input.tryParse(css.Parser.expectString, .{}).asValue()) |s| { + const parsed_columns = switch (parseString(input.allocator(), s, &tokens)) { + .result => |v| v, + .err => return .{input.newError(.qualified_rule_invalid)}, + }; + + if (row == 0) { + columns = parsed_columns; + } else if (parsed_columns != columns) return .{ .err = input.newCustomError(.invalid_declaration) }; + + row += 1; + } + + return .{ .result = .{ .areas = .{ + .columns = columns, + .areas = tokens, + } } }; + } + + const HTML_SPACE_CHARACTERS: []const u8 = &.{ 0x0020, 0x0009, 0x000a, 0x000c, 0x000d }; + + fn parseString(allocator: Allocator, s: []const u8, tokens: *SmallList(?[]const u8, 1)) bun.Maybe(u32, void) { + var string = s; + var column = 0; + + while (true) { + const rest = bun.strings.trim(string, HTML_SPACE_CHARACTERS); + if (rest.len == 0) { + // Each string must produce a valid token. + if (column == 0) return .{ .err = {} }; + break; + } + + column += 1; + + if (bun.strings.startsWithChar(rest, '.')) { + const idx = idx: { + for (rest, 0..) |*c, i| { + if (c.* != '.') { + break :idx i; + } + } + break :idx rest.len; + }; + string = rest[idx..]; + } + + const starts_with_name_codepoint = brk: { + if (rest.len == 0) break :brk false; + break :brk isNameCodepoint(rest[0]); + }; + + if (!starts_with_name_codepoint) return .{ .err = {} }; + + const token_len = token_len: { + for (rest, 0..) |*c, i| { + if (!isNameCodepoint(c.*)) { + break :token_len i; + } + } + break :token_len rest.len; + }; + const token = rest[0..token_len]; + tokens.append(allocator, token) catch bun.outOfMemory(); + string = rest[token_len..]; + } + + return .{ .result = column }; + } +}; + +fn isNameCodepoint(c: u8) bool { + // alpha numeric, -, _, o + return c >= 'a' and c <= 'z' or c >= 'A' and c <= 'Z' or c == '_' or c >= '0' and c <= '9' or c == '-' or c >= 0x80; // codepoints larger than ascii; +} diff --git a/src/css/properties/masking.zig b/src/css/properties/masking.zig index e4d1573ef8b7f3..84062e63f9f5be 100644 --- a/src/css/properties/masking.zig +++ b/src/css/properties/masking.zig @@ -41,6 +41,8 @@ const BorderImageSideWidth = css.css_properties.border_image.BorderImageSideWidt const BorderImageRepeat = css.css_properties.border_image.BorderImageRepeat; const BorderImage = css.css_properties.border_image.BorderImage; +const VendorPrefix = css.VendorPrefix; + /// A value for the [clip-path](https://www.w3.org/TR/css-masking-1/#the-clip-path) property. const ClipPath = union(enum) { /// No clip path. @@ -425,7 +427,7 @@ pub const MaskBorder = struct { /// How the mask image is interpreted. mode: MaskBorderMode, - pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"mask-border"); + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.@"mask-border", PropertyFieldMap); pub const PropertyFieldMap = .{ .source = css.PropertyIdTag.@"mask-border-source", @@ -539,3 +541,17 @@ pub const WebKitMaskSourceType = enum { pub usingnamespace css.DefineEnumProperty(@This()); }; + +pub fn getWebkitMaskProperty(property_id: *const css.PropertyId) ?css.PropertyId { + return switch (property_id.*) { + .@"mask-border-source" => .{ .@"mask-box-image-source" = VendorPrefix.WEBKIT }, + .@"mask-border-slice" => .{ .@"mask-box-image-slice" = VendorPrefix.WEBKIT }, + .@"mask-border-width" => .{ .@"mask-box-image-width" = VendorPrefix.WEBKIT }, + .@"mask-border-outset" => .{ .@"mask-box-image-outset" = VendorPrefix.WEBKIT }, + .@"mask-border-repeat" => .{ .@"mask-box-image-repeat" = VendorPrefix.WEBKIT }, + .@"mask-border" => .{ .@"mask-box-image" = VendorPrefix.WEBKIT }, + .@"mask-composite" => css.PropertyId.@"-webkit-mask-composite", + .@"mask-mode" => .{ .@"mask-source-type" = VendorPrefix.WEBKIT }, + else => null, + }; +} diff --git a/src/css/properties/properties.zig b/src/css/properties/properties.zig index 4ec12ffa41202a..de4c86c79d3e00 100644 --- a/src/css/properties/properties.zig +++ b/src/css/properties/properties.zig @@ -25,6 +25,7 @@ pub const display = @import("./display.zig"); pub const effects = @import("./effects.zig"); pub const flex = @import("./flex.zig"); pub const font = @import("./font.zig"); +pub const grid = @import("./grid.zig"); pub const list = @import("./list.zig"); pub const margin_padding = @import("./margin_padding.zig"); pub const masking = @import("./masking.zig"); diff --git a/src/css/properties/properties_generated.zig b/src/css/properties/properties_generated.zig index 72ea8518265f55..16e6bc6d97af8e 100644 --- a/src/css/properties/properties_generated.zig +++ b/src/css/properties/properties_generated.zig @@ -14,6 +14,19 @@ const PropertyIdImpl = @import("./properties_impl.zig").PropertyIdImpl; const CSSWideKeyword = css.css_properties.CSSWideKeyword; const UnparsedProperty = css.css_properties.custom.UnparsedProperty; const CustomProperty = css.css_properties.custom.CustomProperty; +const Targets = css.targets.Targets; +const Feature = css.prefixes.Feature; + +const ColorScheme = css.css_properties.ui.ColorScheme; + +const TransformList = css.css_properties.transform.TransformList; +const TransformStyle = css.css_properties.transform.TransformStyle; +const TransformBox = css.css_properties.transform.TransformBox; +const BackfaceVisibility = css.css_properties.transform.BackfaceVisibility; +const Perspective = css.css_properties.transform.Perspective; +const Translate = css.css_properties.transform.Translate; +const Rotate = css.css_properties.transform.Rotate; +const Scale = css.css_properties.transform.Scale; const css_values = css.css_values; const CssColor = css.css_values.color.CssColor; @@ -146,7 +159,7 @@ const FontVariantCaps = font.FontVariantCaps; const LineHeight = font.LineHeight; const Font = font.Font; // const VerticalAlign = font.VerticalAlign; -// const Transition = transition.Transition; +const Transition = transition.Transition; // const AnimationNameList = animation.AnimationNameList; // const AnimationList = animation.AnimationList; // const AnimationIterationCount = animation.AnimationIterationCount; @@ -443,6 +456,21 @@ pub const Property = union(PropertyIdTag) { @"font-variant-caps": FontVariantCaps, @"line-height": LineHeight, font: Font, + @"transition-property": struct { SmallList(PropertyId, 1), VendorPrefix }, + @"transition-duration": struct { SmallList(Time, 1), VendorPrefix }, + @"transition-delay": struct { SmallList(Time, 1), VendorPrefix }, + @"transition-timing-function": struct { SmallList(EasingFunction, 1), VendorPrefix }, + transition: struct { SmallList(Transition, 1), VendorPrefix }, + transform: struct { TransformList, VendorPrefix }, + @"transform-origin": struct { Position, VendorPrefix }, + @"transform-style": struct { TransformStyle, VendorPrefix }, + @"transform-box": TransformBox, + @"backface-visibility": struct { BackfaceVisibility, VendorPrefix }, + perspective: struct { Perspective, VendorPrefix }, + @"perspective-origin": struct { Position, VendorPrefix }, + translate: Translate, + rotate: Rotate, + scale: Scale, @"text-decoration-color": struct { CssColor, VendorPrefix }, @"text-emphasis-color": struct { CssColor, VendorPrefix }, @"text-shadow": SmallList(TextShadow, 1), @@ -475,6 +503,7 @@ pub const Property = union(PropertyIdTag) { @"mask-box-image-width": struct { Rect(BorderImageSideWidth), VendorPrefix }, @"mask-box-image-outset": struct { Rect(LengthOrNumber), VendorPrefix }, @"mask-box-image-repeat": struct { BorderImageRepeat, VendorPrefix }, + @"color-scheme": ColorScheme, all: CSSWideKeyword, unparsed: UnparsedProperty, custom: CustomProperty, @@ -3517,6 +3546,246 @@ pub const Property = union(PropertyIdTag) { compile_error = compile_error ++ @typeName(Font) ++ ": does not have a eql() function.\n"; } + if (!@hasDecl(SmallList(PropertyId, 1), "deepClone")) { + compile_error = compile_error ++ @typeName(SmallList(PropertyId, 1)) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(SmallList(PropertyId, 1), "parse")) { + compile_error = compile_error ++ @typeName(SmallList(PropertyId, 1)) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(SmallList(PropertyId, 1), "toCss")) { + compile_error = compile_error ++ @typeName(SmallList(PropertyId, 1)) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(SmallList(PropertyId, 1), "eql")) { + compile_error = compile_error ++ @typeName(SmallList(PropertyId, 1)) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "deepClone")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "parse")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "toCss")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "eql")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "deepClone")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "parse")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "toCss")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(SmallList(Time, 1), "eql")) { + compile_error = compile_error ++ @typeName(SmallList(Time, 1)) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(SmallList(EasingFunction, 1), "deepClone")) { + compile_error = compile_error ++ @typeName(SmallList(EasingFunction, 1)) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(SmallList(EasingFunction, 1), "parse")) { + compile_error = compile_error ++ @typeName(SmallList(EasingFunction, 1)) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(SmallList(EasingFunction, 1), "toCss")) { + compile_error = compile_error ++ @typeName(SmallList(EasingFunction, 1)) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(SmallList(EasingFunction, 1), "eql")) { + compile_error = compile_error ++ @typeName(SmallList(EasingFunction, 1)) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(SmallList(Transition, 1), "deepClone")) { + compile_error = compile_error ++ @typeName(SmallList(Transition, 1)) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(SmallList(Transition, 1), "parse")) { + compile_error = compile_error ++ @typeName(SmallList(Transition, 1)) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(SmallList(Transition, 1), "toCss")) { + compile_error = compile_error ++ @typeName(SmallList(Transition, 1)) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(SmallList(Transition, 1), "eql")) { + compile_error = compile_error ++ @typeName(SmallList(Transition, 1)) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(TransformList, "deepClone")) { + compile_error = compile_error ++ @typeName(TransformList) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(TransformList, "parse")) { + compile_error = compile_error ++ @typeName(TransformList) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(TransformList, "toCss")) { + compile_error = compile_error ++ @typeName(TransformList) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(TransformList, "eql")) { + compile_error = compile_error ++ @typeName(TransformList) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(Position, "deepClone")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(Position, "parse")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(Position, "toCss")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(Position, "eql")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(TransformStyle, "deepClone")) { + compile_error = compile_error ++ @typeName(TransformStyle) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(TransformStyle, "parse")) { + compile_error = compile_error ++ @typeName(TransformStyle) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(TransformStyle, "toCss")) { + compile_error = compile_error ++ @typeName(TransformStyle) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(TransformStyle, "eql")) { + compile_error = compile_error ++ @typeName(TransformStyle) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(TransformBox, "deepClone")) { + compile_error = compile_error ++ @typeName(TransformBox) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(TransformBox, "parse")) { + compile_error = compile_error ++ @typeName(TransformBox) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(TransformBox, "toCss")) { + compile_error = compile_error ++ @typeName(TransformBox) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(TransformBox, "eql")) { + compile_error = compile_error ++ @typeName(TransformBox) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(BackfaceVisibility, "deepClone")) { + compile_error = compile_error ++ @typeName(BackfaceVisibility) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(BackfaceVisibility, "parse")) { + compile_error = compile_error ++ @typeName(BackfaceVisibility) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(BackfaceVisibility, "toCss")) { + compile_error = compile_error ++ @typeName(BackfaceVisibility) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(BackfaceVisibility, "eql")) { + compile_error = compile_error ++ @typeName(BackfaceVisibility) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(Perspective, "deepClone")) { + compile_error = compile_error ++ @typeName(Perspective) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(Perspective, "parse")) { + compile_error = compile_error ++ @typeName(Perspective) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(Perspective, "toCss")) { + compile_error = compile_error ++ @typeName(Perspective) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(Perspective, "eql")) { + compile_error = compile_error ++ @typeName(Perspective) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(Position, "deepClone")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(Position, "parse")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(Position, "toCss")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(Position, "eql")) { + compile_error = compile_error ++ @typeName(Position) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(Translate, "deepClone")) { + compile_error = compile_error ++ @typeName(Translate) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(Translate, "parse")) { + compile_error = compile_error ++ @typeName(Translate) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(Translate, "toCss")) { + compile_error = compile_error ++ @typeName(Translate) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(Translate, "eql")) { + compile_error = compile_error ++ @typeName(Translate) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(Rotate, "deepClone")) { + compile_error = compile_error ++ @typeName(Rotate) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(Rotate, "parse")) { + compile_error = compile_error ++ @typeName(Rotate) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(Rotate, "toCss")) { + compile_error = compile_error ++ @typeName(Rotate) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(Rotate, "eql")) { + compile_error = compile_error ++ @typeName(Rotate) ++ ": does not have a eql() function.\n"; + } + + if (!@hasDecl(Scale, "deepClone")) { + compile_error = compile_error ++ @typeName(Scale) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(Scale, "parse")) { + compile_error = compile_error ++ @typeName(Scale) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(Scale, "toCss")) { + compile_error = compile_error ++ @typeName(Scale) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(Scale, "eql")) { + compile_error = compile_error ++ @typeName(Scale) ++ ": does not have a eql() function.\n"; + } + if (!@hasDecl(CssColor, "deepClone")) { compile_error = compile_error ++ @typeName(CssColor) ++ ": does not have a deepClone() function.\n"; } @@ -4029,6 +4298,22 @@ pub const Property = union(PropertyIdTag) { compile_error = compile_error ++ @typeName(BorderImageRepeat) ++ ": does not have a eql() function.\n"; } + if (!@hasDecl(ColorScheme, "deepClone")) { + compile_error = compile_error ++ @typeName(ColorScheme) ++ ": does not have a deepClone() function.\n"; + } + + if (!@hasDecl(ColorScheme, "parse")) { + compile_error = compile_error ++ @typeName(ColorScheme) ++ ": does not have a parse() function.\n"; + } + + if (!@hasDecl(ColorScheme, "toCss")) { + compile_error = compile_error ++ @typeName(ColorScheme) ++ ": does not have a toCss() function.\n"; + } + + if (!@hasDecl(ColorScheme, "eql")) { + compile_error = compile_error ++ @typeName(ColorScheme) ++ ": does not have a eql() function.\n"; + } + const final_compile_error = compile_error; break :compile_error final_compile_error; }; @@ -5431,6 +5716,111 @@ pub const Property = union(PropertyIdTag) { } } }, + .@"transition-property" => |pre| { + if (css.generic.parseWithOptions(SmallList(PropertyId, 1), input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transition-property" = .{ c, pre } } }; + } + } + }, + .@"transition-duration" => |pre| { + if (css.generic.parseWithOptions(SmallList(Time, 1), input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transition-duration" = .{ c, pre } } }; + } + } + }, + .@"transition-delay" => |pre| { + if (css.generic.parseWithOptions(SmallList(Time, 1), input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transition-delay" = .{ c, pre } } }; + } + } + }, + .@"transition-timing-function" => |pre| { + if (css.generic.parseWithOptions(SmallList(EasingFunction, 1), input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transition-timing-function" = .{ c, pre } } }; + } + } + }, + .transition => |pre| { + if (css.generic.parseWithOptions(SmallList(Transition, 1), input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .transition = .{ c, pre } } }; + } + } + }, + .transform => |pre| { + if (css.generic.parseWithOptions(TransformList, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .transform = .{ c, pre } } }; + } + } + }, + .@"transform-origin" => |pre| { + if (css.generic.parseWithOptions(Position, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transform-origin" = .{ c, pre } } }; + } + } + }, + .@"transform-style" => |pre| { + if (css.generic.parseWithOptions(TransformStyle, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transform-style" = .{ c, pre } } }; + } + } + }, + .@"transform-box" => { + if (css.generic.parseWithOptions(TransformBox, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"transform-box" = c } }; + } + } + }, + .@"backface-visibility" => |pre| { + if (css.generic.parseWithOptions(BackfaceVisibility, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"backface-visibility" = .{ c, pre } } }; + } + } + }, + .perspective => |pre| { + if (css.generic.parseWithOptions(Perspective, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .perspective = .{ c, pre } } }; + } + } + }, + .@"perspective-origin" => |pre| { + if (css.generic.parseWithOptions(Position, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"perspective-origin" = .{ c, pre } } }; + } + } + }, + .translate => { + if (css.generic.parseWithOptions(Translate, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .translate = c } }; + } + } + }, + .rotate => { + if (css.generic.parseWithOptions(Rotate, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .rotate = c } }; + } + } + }, + .scale => { + if (css.generic.parseWithOptions(Scale, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .scale = c } }; + } + } + }, .@"text-decoration-color" => |pre| { if (css.generic.parseWithOptions(CssColor, input, options).asValue()) |c| { if (input.expectExhausted().isOk()) { @@ -5656,6 +6046,13 @@ pub const Property = union(PropertyIdTag) { } } }, + .@"color-scheme" => { + if (css.generic.parseWithOptions(ColorScheme, input, options).asValue()) |c| { + if (input.expectExhausted().isOk()) { + return .{ .result = .{ .@"color-scheme" = c } }; + } + } + }, .all => return .{ .result = .{ .all = switch (CSSWideKeyword.parse(input)) { .result => |v| v, .err => |e| return .{ .err = e }, @@ -5878,6 +6275,21 @@ pub const Property = union(PropertyIdTag) { .@"font-variant-caps" => .@"font-variant-caps", .@"line-height" => .@"line-height", .font => .font, + .@"transition-property" => |*v| PropertyId{ .@"transition-property" = v[1] }, + .@"transition-duration" => |*v| PropertyId{ .@"transition-duration" = v[1] }, + .@"transition-delay" => |*v| PropertyId{ .@"transition-delay" = v[1] }, + .@"transition-timing-function" => |*v| PropertyId{ .@"transition-timing-function" = v[1] }, + .transition => |*v| PropertyId{ .transition = v[1] }, + .transform => |*v| PropertyId{ .transform = v[1] }, + .@"transform-origin" => |*v| PropertyId{ .@"transform-origin" = v[1] }, + .@"transform-style" => |*v| PropertyId{ .@"transform-style" = v[1] }, + .@"transform-box" => .@"transform-box", + .@"backface-visibility" => |*v| PropertyId{ .@"backface-visibility" = v[1] }, + .perspective => |*v| PropertyId{ .perspective = v[1] }, + .@"perspective-origin" => |*v| PropertyId{ .@"perspective-origin" = v[1] }, + .translate => .translate, + .rotate => .rotate, + .scale => .scale, .@"text-decoration-color" => |*v| PropertyId{ .@"text-decoration-color" = v[1] }, .@"text-emphasis-color" => |*v| PropertyId{ .@"text-emphasis-color" = v[1] }, .@"text-shadow" => .@"text-shadow", @@ -5910,6 +6322,7 @@ pub const Property = union(PropertyIdTag) { .@"mask-box-image-width" => |*v| PropertyId{ .@"mask-box-image-width" = v[1] }, .@"mask-box-image-outset" => |*v| PropertyId{ .@"mask-box-image-outset" = v[1] }, .@"mask-box-image-repeat" => |*v| PropertyId{ .@"mask-box-image-repeat" = v[1] }, + .@"color-scheme" => .@"color-scheme", .all => PropertyId.all, .unparsed => |unparsed| unparsed.property_id, .custom => |c| .{ .custom = c.name }, @@ -6116,6 +6529,21 @@ pub const Property = union(PropertyIdTag) { .@"font-variant-caps" => |*v| .{ .@"font-variant-caps" = v.deepClone(allocator) }, .@"line-height" => |*v| .{ .@"line-height" = v.deepClone(allocator) }, .font => |*v| .{ .font = v.deepClone(allocator) }, + .@"transition-property" => |*v| .{ .@"transition-property" = .{ v[0].deepClone(allocator), v[1] } }, + .@"transition-duration" => |*v| .{ .@"transition-duration" = .{ v[0].deepClone(allocator), v[1] } }, + .@"transition-delay" => |*v| .{ .@"transition-delay" = .{ v[0].deepClone(allocator), v[1] } }, + .@"transition-timing-function" => |*v| .{ .@"transition-timing-function" = .{ v[0].deepClone(allocator), v[1] } }, + .transition => |*v| .{ .transition = .{ v[0].deepClone(allocator), v[1] } }, + .transform => |*v| .{ .transform = .{ v[0].deepClone(allocator), v[1] } }, + .@"transform-origin" => |*v| .{ .@"transform-origin" = .{ v[0].deepClone(allocator), v[1] } }, + .@"transform-style" => |*v| .{ .@"transform-style" = .{ v[0].deepClone(allocator), v[1] } }, + .@"transform-box" => |*v| .{ .@"transform-box" = v.deepClone(allocator) }, + .@"backface-visibility" => |*v| .{ .@"backface-visibility" = .{ v[0].deepClone(allocator), v[1] } }, + .perspective => |*v| .{ .perspective = .{ v[0].deepClone(allocator), v[1] } }, + .@"perspective-origin" => |*v| .{ .@"perspective-origin" = .{ v[0].deepClone(allocator), v[1] } }, + .translate => |*v| .{ .translate = v.deepClone(allocator) }, + .rotate => |*v| .{ .rotate = v.deepClone(allocator) }, + .scale => |*v| .{ .scale = v.deepClone(allocator) }, .@"text-decoration-color" => |*v| .{ .@"text-decoration-color" = .{ v[0].deepClone(allocator), v[1] } }, .@"text-emphasis-color" => |*v| .{ .@"text-emphasis-color" = .{ v[0].deepClone(allocator), v[1] } }, .@"text-shadow" => |*v| .{ .@"text-shadow" = v.deepClone(allocator) }, @@ -6148,6 +6576,7 @@ pub const Property = union(PropertyIdTag) { .@"mask-box-image-width" => |*v| .{ .@"mask-box-image-width" = .{ v[0].deepClone(allocator), v[1] } }, .@"mask-box-image-outset" => |*v| .{ .@"mask-box-image-outset" = .{ v[0].deepClone(allocator), v[1] } }, .@"mask-box-image-repeat" => |*v| .{ .@"mask-box-image-repeat" = .{ v[0].deepClone(allocator), v[1] } }, + .@"color-scheme" => |*v| .{ .@"color-scheme" = v.deepClone(allocator) }, .all => |*a| return .{ .all = a.deepClone(allocator) }, .unparsed => |*u| return .{ .unparsed = u.deepClone(allocator) }, .custom => |*c| return .{ .custom = c.deepClone(allocator) }, @@ -6364,6 +6793,21 @@ pub const Property = union(PropertyIdTag) { .@"font-variant-caps" => .{ "font-variant-caps", VendorPrefix{ .none = true } }, .@"line-height" => .{ "line-height", VendorPrefix{ .none = true } }, .font => .{ "font", VendorPrefix{ .none = true } }, + .@"transition-property" => |*x| .{ "transition-property", x.@"1" }, + .@"transition-duration" => |*x| .{ "transition-duration", x.@"1" }, + .@"transition-delay" => |*x| .{ "transition-delay", x.@"1" }, + .@"transition-timing-function" => |*x| .{ "transition-timing-function", x.@"1" }, + .transition => |*x| .{ "transition", x.@"1" }, + .transform => |*x| .{ "transform", x.@"1" }, + .@"transform-origin" => |*x| .{ "transform-origin", x.@"1" }, + .@"transform-style" => |*x| .{ "transform-style", x.@"1" }, + .@"transform-box" => .{ "transform-box", VendorPrefix{ .none = true } }, + .@"backface-visibility" => |*x| .{ "backface-visibility", x.@"1" }, + .perspective => |*x| .{ "perspective", x.@"1" }, + .@"perspective-origin" => |*x| .{ "perspective-origin", x.@"1" }, + .translate => .{ "translate", VendorPrefix{ .none = true } }, + .rotate => .{ "rotate", VendorPrefix{ .none = true } }, + .scale => .{ "scale", VendorPrefix{ .none = true } }, .@"text-decoration-color" => |*x| .{ "text-decoration-color", x.@"1" }, .@"text-emphasis-color" => |*x| .{ "text-emphasis-color", x.@"1" }, .@"text-shadow" => .{ "text-shadow", VendorPrefix{ .none = true } }, @@ -6396,6 +6840,7 @@ pub const Property = union(PropertyIdTag) { .@"mask-box-image-width" => |*x| .{ "mask-box-image-width", x.@"1" }, .@"mask-box-image-outset" => |*x| .{ "mask-box-image-outset", x.@"1" }, .@"mask-box-image-repeat" => |*x| .{ "mask-box-image-repeat", x.@"1" }, + .@"color-scheme" => .{ "color-scheme", VendorPrefix{ .none = true } }, .all => .{ "all", VendorPrefix{ .none = true } }, .unparsed => |*unparsed| brk: { var prefix = unparsed.property_id.prefix(); @@ -6609,6 +7054,21 @@ pub const Property = union(PropertyIdTag) { .@"font-variant-caps" => |*value| value.toCss(W, dest), .@"line-height" => |*value| value.toCss(W, dest), .font => |*value| value.toCss(W, dest), + .@"transition-property" => |*value| value[0].toCss(W, dest), + .@"transition-duration" => |*value| value[0].toCss(W, dest), + .@"transition-delay" => |*value| value[0].toCss(W, dest), + .@"transition-timing-function" => |*value| value[0].toCss(W, dest), + .transition => |*value| value[0].toCss(W, dest), + .transform => |*value| value[0].toCss(W, dest), + .@"transform-origin" => |*value| value[0].toCss(W, dest), + .@"transform-style" => |*value| value[0].toCss(W, dest), + .@"transform-box" => |*value| value.toCss(W, dest), + .@"backface-visibility" => |*value| value[0].toCss(W, dest), + .perspective => |*value| value[0].toCss(W, dest), + .@"perspective-origin" => |*value| value[0].toCss(W, dest), + .translate => |*value| value.toCss(W, dest), + .rotate => |*value| value.toCss(W, dest), + .scale => |*value| value.toCss(W, dest), .@"text-decoration-color" => |*value| value[0].toCss(W, dest), .@"text-emphasis-color" => |*value| value[0].toCss(W, dest), .@"text-shadow" => |*value| value.toCss(W, dest), @@ -6641,6 +7101,7 @@ pub const Property = union(PropertyIdTag) { .@"mask-box-image-width" => |*value| value[0].toCss(W, dest), .@"mask-box-image-outset" => |*value| value[0].toCss(W, dest), .@"mask-box-image-repeat" => |*value| value[0].toCss(W, dest), + .@"color-scheme" => |*value| value.toCss(W, dest), .all => |*keyword| keyword.toCss(W, dest), .unparsed => |*unparsed| unparsed.value.toCss(W, dest, false), .custom => |*c| c.value.toCss(W, dest, c.name == .custom), @@ -6709,6 +7170,10 @@ pub const Property = union(PropertyIdTag) { .@"scroll-padding-inline" => |*v| return v.longhand(property_id), .@"scroll-padding" => |*v| return v.longhand(property_id), .font => |*v| return v.longhand(property_id), + .transition => |*v| { + if (!v[1].eq(property_id.prefix())) return null; + return v[0].longhand(property_id); + }, .mask => |*v| { if (!v[1].eq(property_id.prefix())) return null; return v[0].longhand(property_id); @@ -6920,6 +7385,21 @@ pub const Property = union(PropertyIdTag) { .@"font-variant-caps" => |*v| css.generic.eql(FontVariantCaps, v, &rhs.@"font-variant-caps"), .@"line-height" => |*v| css.generic.eql(LineHeight, v, &rhs.@"line-height"), .font => |*v| css.generic.eql(Font, v, &rhs.font), + .@"transition-property" => |*v| css.generic.eql(SmallList(PropertyId, 1), &v[0], &rhs.@"transition-property"[0]) and v[1].eq(rhs.@"transition-property"[1]), + .@"transition-duration" => |*v| css.generic.eql(SmallList(Time, 1), &v[0], &rhs.@"transition-duration"[0]) and v[1].eq(rhs.@"transition-duration"[1]), + .@"transition-delay" => |*v| css.generic.eql(SmallList(Time, 1), &v[0], &rhs.@"transition-delay"[0]) and v[1].eq(rhs.@"transition-delay"[1]), + .@"transition-timing-function" => |*v| css.generic.eql(SmallList(EasingFunction, 1), &v[0], &rhs.@"transition-timing-function"[0]) and v[1].eq(rhs.@"transition-timing-function"[1]), + .transition => |*v| css.generic.eql(SmallList(Transition, 1), &v[0], &rhs.transition[0]) and v[1].eq(rhs.transition[1]), + .transform => |*v| css.generic.eql(TransformList, &v[0], &rhs.transform[0]) and v[1].eq(rhs.transform[1]), + .@"transform-origin" => |*v| css.generic.eql(Position, &v[0], &rhs.@"transform-origin"[0]) and v[1].eq(rhs.@"transform-origin"[1]), + .@"transform-style" => |*v| css.generic.eql(TransformStyle, &v[0], &rhs.@"transform-style"[0]) and v[1].eq(rhs.@"transform-style"[1]), + .@"transform-box" => |*v| css.generic.eql(TransformBox, v, &rhs.@"transform-box"), + .@"backface-visibility" => |*v| css.generic.eql(BackfaceVisibility, &v[0], &rhs.@"backface-visibility"[0]) and v[1].eq(rhs.@"backface-visibility"[1]), + .perspective => |*v| css.generic.eql(Perspective, &v[0], &rhs.perspective[0]) and v[1].eq(rhs.perspective[1]), + .@"perspective-origin" => |*v| css.generic.eql(Position, &v[0], &rhs.@"perspective-origin"[0]) and v[1].eq(rhs.@"perspective-origin"[1]), + .translate => |*v| css.generic.eql(Translate, v, &rhs.translate), + .rotate => |*v| css.generic.eql(Rotate, v, &rhs.rotate), + .scale => |*v| css.generic.eql(Scale, v, &rhs.scale), .@"text-decoration-color" => |*v| css.generic.eql(CssColor, &v[0], &rhs.@"text-decoration-color"[0]) and v[1].eq(rhs.@"text-decoration-color"[1]), .@"text-emphasis-color" => |*v| css.generic.eql(CssColor, &v[0], &rhs.@"text-emphasis-color"[0]) and v[1].eq(rhs.@"text-emphasis-color"[1]), .@"text-shadow" => |*v| css.generic.eql(SmallList(TextShadow, 1), v, &rhs.@"text-shadow"), @@ -6952,6 +7432,7 @@ pub const Property = union(PropertyIdTag) { .@"mask-box-image-width" => |*v| css.generic.eql(Rect(BorderImageSideWidth), &v[0], &rhs.@"mask-box-image-width"[0]) and v[1].eq(rhs.@"mask-box-image-width"[1]), .@"mask-box-image-outset" => |*v| css.generic.eql(Rect(LengthOrNumber), &v[0], &rhs.@"mask-box-image-outset"[0]) and v[1].eq(rhs.@"mask-box-image-outset"[1]), .@"mask-box-image-repeat" => |*v| css.generic.eql(BorderImageRepeat, &v[0], &rhs.@"mask-box-image-repeat"[0]) and v[1].eq(rhs.@"mask-box-image-repeat"[1]), + .@"color-scheme" => |*v| css.generic.eql(ColorScheme, v, &rhs.@"color-scheme"), .unparsed => |*u| u.eql(&rhs.unparsed), .all => true, .custom => |*c| c.eql(&rhs.custom), @@ -7157,6 +7638,21 @@ pub const PropertyId = union(PropertyIdTag) { @"font-variant-caps", @"line-height", font, + @"transition-property": VendorPrefix, + @"transition-duration": VendorPrefix, + @"transition-delay": VendorPrefix, + @"transition-timing-function": VendorPrefix, + transition: VendorPrefix, + transform: VendorPrefix, + @"transform-origin": VendorPrefix, + @"transform-style": VendorPrefix, + @"transform-box", + @"backface-visibility": VendorPrefix, + perspective: VendorPrefix, + @"perspective-origin": VendorPrefix, + translate, + rotate, + scale, @"text-decoration-color": VendorPrefix, @"text-emphasis-color": VendorPrefix, @"text-shadow", @@ -7189,6 +7685,7 @@ pub const PropertyId = union(PropertyIdTag) { @"mask-box-image-width": VendorPrefix, @"mask-box-image-outset": VendorPrefix, @"mask-box-image-repeat": VendorPrefix, + @"color-scheme", all, unparsed, custom: CustomPropertyName, @@ -7402,6 +7899,21 @@ pub const PropertyId = union(PropertyIdTag) { .@"font-variant-caps" => VendorPrefix.empty(), .@"line-height" => VendorPrefix.empty(), .font => VendorPrefix.empty(), + .@"transition-property" => |p| p, + .@"transition-duration" => |p| p, + .@"transition-delay" => |p| p, + .@"transition-timing-function" => |p| p, + .transition => |p| p, + .transform => |p| p, + .@"transform-origin" => |p| p, + .@"transform-style" => |p| p, + .@"transform-box" => VendorPrefix.empty(), + .@"backface-visibility" => |p| p, + .perspective => |p| p, + .@"perspective-origin" => |p| p, + .translate => VendorPrefix.empty(), + .rotate => VendorPrefix.empty(), + .scale => VendorPrefix.empty(), .@"text-decoration-color" => |p| p, .@"text-emphasis-color" => |p| p, .@"text-shadow" => VendorPrefix.empty(), @@ -7434,12 +7946,13 @@ pub const PropertyId = union(PropertyIdTag) { .@"mask-box-image-width" => |p| p, .@"mask-box-image-outset" => |p| p, .@"mask-box-image-repeat" => |p| p, + .@"color-scheme" => VendorPrefix.empty(), .all, .custom, .unparsed => VendorPrefix.empty(), }; } pub fn fromNameAndPrefix(name1: []const u8, pre: VendorPrefix) ?PropertyId { - const Enum = enum { @"background-color", @"background-image", @"background-position-x", @"background-position-y", @"background-position", @"background-size", @"background-repeat", @"background-attachment", @"background-clip", @"background-origin", background, @"box-shadow", opacity, color, display, visibility, width, height, @"min-width", @"min-height", @"max-width", @"max-height", @"block-size", @"inline-size", @"min-block-size", @"min-inline-size", @"max-block-size", @"max-inline-size", @"box-sizing", @"aspect-ratio", overflow, @"overflow-x", @"overflow-y", @"text-overflow", position, top, bottom, left, right, @"inset-block-start", @"inset-block-end", @"inset-inline-start", @"inset-inline-end", @"inset-block", @"inset-inline", inset, @"border-spacing", @"border-top-color", @"border-bottom-color", @"border-left-color", @"border-right-color", @"border-block-start-color", @"border-block-end-color", @"border-inline-start-color", @"border-inline-end-color", @"border-top-style", @"border-bottom-style", @"border-left-style", @"border-right-style", @"border-block-start-style", @"border-block-end-style", @"border-inline-start-style", @"border-inline-end-style", @"border-top-width", @"border-bottom-width", @"border-left-width", @"border-right-width", @"border-block-start-width", @"border-block-end-width", @"border-inline-start-width", @"border-inline-end-width", @"border-top-left-radius", @"border-top-right-radius", @"border-bottom-left-radius", @"border-bottom-right-radius", @"border-start-start-radius", @"border-start-end-radius", @"border-end-start-radius", @"border-end-end-radius", @"border-radius", @"border-image-source", @"border-image-outset", @"border-image-repeat", @"border-image-width", @"border-image-slice", @"border-image", @"border-color", @"border-style", @"border-width", @"border-block-color", @"border-block-style", @"border-block-width", @"border-inline-color", @"border-inline-style", @"border-inline-width", border, @"border-top", @"border-bottom", @"border-left", @"border-right", @"border-block", @"border-block-start", @"border-block-end", @"border-inline", @"border-inline-start", @"border-inline-end", outline, @"outline-color", @"outline-style", @"outline-width", @"flex-direction", @"flex-wrap", @"flex-flow", @"flex-grow", @"flex-shrink", @"flex-basis", flex, order, @"align-content", @"justify-content", @"place-content", @"align-self", @"justify-self", @"place-self", @"align-items", @"justify-items", @"place-items", @"row-gap", @"column-gap", gap, @"box-orient", @"box-direction", @"box-ordinal-group", @"box-align", @"box-flex", @"box-flex-group", @"box-pack", @"box-lines", @"flex-pack", @"flex-order", @"flex-align", @"flex-item-align", @"flex-line-pack", @"flex-positive", @"flex-negative", @"flex-preferred-size", @"margin-top", @"margin-bottom", @"margin-left", @"margin-right", @"margin-block-start", @"margin-block-end", @"margin-inline-start", @"margin-inline-end", @"margin-block", @"margin-inline", margin, @"padding-top", @"padding-bottom", @"padding-left", @"padding-right", @"padding-block-start", @"padding-block-end", @"padding-inline-start", @"padding-inline-end", @"padding-block", @"padding-inline", padding, @"scroll-margin-top", @"scroll-margin-bottom", @"scroll-margin-left", @"scroll-margin-right", @"scroll-margin-block-start", @"scroll-margin-block-end", @"scroll-margin-inline-start", @"scroll-margin-inline-end", @"scroll-margin-block", @"scroll-margin-inline", @"scroll-margin", @"scroll-padding-top", @"scroll-padding-bottom", @"scroll-padding-left", @"scroll-padding-right", @"scroll-padding-block-start", @"scroll-padding-block-end", @"scroll-padding-inline-start", @"scroll-padding-inline-end", @"scroll-padding-block", @"scroll-padding-inline", @"scroll-padding", @"font-weight", @"font-size", @"font-stretch", @"font-family", @"font-style", @"font-variant-caps", @"line-height", font, @"text-decoration-color", @"text-emphasis-color", @"text-shadow", direction, composes, @"mask-image", @"mask-mode", @"mask-repeat", @"mask-position-x", @"mask-position-y", @"mask-position", @"mask-clip", @"mask-origin", @"mask-size", @"mask-composite", @"mask-type", mask, @"mask-border-source", @"mask-border-mode", @"mask-border-slice", @"mask-border-width", @"mask-border-outset", @"mask-border-repeat", @"mask-border", @"-webkit-mask-composite", @"mask-source-type", @"mask-box-image", @"mask-box-image-source", @"mask-box-image-slice", @"mask-box-image-width", @"mask-box-image-outset", @"mask-box-image-repeat" }; + const Enum = enum { @"background-color", @"background-image", @"background-position-x", @"background-position-y", @"background-position", @"background-size", @"background-repeat", @"background-attachment", @"background-clip", @"background-origin", background, @"box-shadow", opacity, color, display, visibility, width, height, @"min-width", @"min-height", @"max-width", @"max-height", @"block-size", @"inline-size", @"min-block-size", @"min-inline-size", @"max-block-size", @"max-inline-size", @"box-sizing", @"aspect-ratio", overflow, @"overflow-x", @"overflow-y", @"text-overflow", position, top, bottom, left, right, @"inset-block-start", @"inset-block-end", @"inset-inline-start", @"inset-inline-end", @"inset-block", @"inset-inline", inset, @"border-spacing", @"border-top-color", @"border-bottom-color", @"border-left-color", @"border-right-color", @"border-block-start-color", @"border-block-end-color", @"border-inline-start-color", @"border-inline-end-color", @"border-top-style", @"border-bottom-style", @"border-left-style", @"border-right-style", @"border-block-start-style", @"border-block-end-style", @"border-inline-start-style", @"border-inline-end-style", @"border-top-width", @"border-bottom-width", @"border-left-width", @"border-right-width", @"border-block-start-width", @"border-block-end-width", @"border-inline-start-width", @"border-inline-end-width", @"border-top-left-radius", @"border-top-right-radius", @"border-bottom-left-radius", @"border-bottom-right-radius", @"border-start-start-radius", @"border-start-end-radius", @"border-end-start-radius", @"border-end-end-radius", @"border-radius", @"border-image-source", @"border-image-outset", @"border-image-repeat", @"border-image-width", @"border-image-slice", @"border-image", @"border-color", @"border-style", @"border-width", @"border-block-color", @"border-block-style", @"border-block-width", @"border-inline-color", @"border-inline-style", @"border-inline-width", border, @"border-top", @"border-bottom", @"border-left", @"border-right", @"border-block", @"border-block-start", @"border-block-end", @"border-inline", @"border-inline-start", @"border-inline-end", outline, @"outline-color", @"outline-style", @"outline-width", @"flex-direction", @"flex-wrap", @"flex-flow", @"flex-grow", @"flex-shrink", @"flex-basis", flex, order, @"align-content", @"justify-content", @"place-content", @"align-self", @"justify-self", @"place-self", @"align-items", @"justify-items", @"place-items", @"row-gap", @"column-gap", gap, @"box-orient", @"box-direction", @"box-ordinal-group", @"box-align", @"box-flex", @"box-flex-group", @"box-pack", @"box-lines", @"flex-pack", @"flex-order", @"flex-align", @"flex-item-align", @"flex-line-pack", @"flex-positive", @"flex-negative", @"flex-preferred-size", @"margin-top", @"margin-bottom", @"margin-left", @"margin-right", @"margin-block-start", @"margin-block-end", @"margin-inline-start", @"margin-inline-end", @"margin-block", @"margin-inline", margin, @"padding-top", @"padding-bottom", @"padding-left", @"padding-right", @"padding-block-start", @"padding-block-end", @"padding-inline-start", @"padding-inline-end", @"padding-block", @"padding-inline", padding, @"scroll-margin-top", @"scroll-margin-bottom", @"scroll-margin-left", @"scroll-margin-right", @"scroll-margin-block-start", @"scroll-margin-block-end", @"scroll-margin-inline-start", @"scroll-margin-inline-end", @"scroll-margin-block", @"scroll-margin-inline", @"scroll-margin", @"scroll-padding-top", @"scroll-padding-bottom", @"scroll-padding-left", @"scroll-padding-right", @"scroll-padding-block-start", @"scroll-padding-block-end", @"scroll-padding-inline-start", @"scroll-padding-inline-end", @"scroll-padding-block", @"scroll-padding-inline", @"scroll-padding", @"font-weight", @"font-size", @"font-stretch", @"font-family", @"font-style", @"font-variant-caps", @"line-height", font, @"transition-property", @"transition-duration", @"transition-delay", @"transition-timing-function", transition, transform, @"transform-origin", @"transform-style", @"transform-box", @"backface-visibility", perspective, @"perspective-origin", translate, rotate, scale, @"text-decoration-color", @"text-emphasis-color", @"text-shadow", direction, composes, @"mask-image", @"mask-mode", @"mask-repeat", @"mask-position-x", @"mask-position-y", @"mask-position", @"mask-clip", @"mask-origin", @"mask-size", @"mask-composite", @"mask-type", mask, @"mask-border-source", @"mask-border-mode", @"mask-border-slice", @"mask-border-width", @"mask-border-outset", @"mask-border-repeat", @"mask-border", @"-webkit-mask-composite", @"mask-source-type", @"mask-box-image", @"mask-box-image-source", @"mask-box-image-slice", @"mask-box-image-width", @"mask-box-image-outset", @"mask-box-image-repeat", @"color-scheme" }; const Map = comptime bun.ComptimeEnumMap(Enum); if (Map.getASCIIICaseInsensitive(name1)) |prop| { switch (prop) { @@ -8235,6 +8748,66 @@ pub const PropertyId = union(PropertyIdTag) { const allowed_prefixes = VendorPrefix{ .none = true }; if (allowed_prefixes.contains(pre)) return .font; }, + .@"transition-property" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"transition-property" = pre }; + }, + .@"transition-duration" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"transition-duration" = pre }; + }, + .@"transition-delay" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"transition-delay" = pre }; + }, + .@"transition-timing-function" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"transition-timing-function" = pre }; + }, + .transition => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true }; + if (allowed_prefixes.contains(pre)) return .{ .transition = pre }; + }, + .transform => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true, .o = true }; + if (allowed_prefixes.contains(pre)) return .{ .transform = pre }; + }, + .@"transform-origin" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true, .ms = true, .o = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"transform-origin" = pre }; + }, + .@"transform-style" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"transform-style" = pre }; + }, + .@"transform-box" => { + const allowed_prefixes = VendorPrefix{ .none = true }; + if (allowed_prefixes.contains(pre)) return .@"transform-box"; + }, + .@"backface-visibility" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"backface-visibility" = pre }; + }, + .perspective => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true }; + if (allowed_prefixes.contains(pre)) return .{ .perspective = pre }; + }, + .@"perspective-origin" => { + const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true }; + if (allowed_prefixes.contains(pre)) return .{ .@"perspective-origin" = pre }; + }, + .translate => { + const allowed_prefixes = VendorPrefix{ .none = true }; + if (allowed_prefixes.contains(pre)) return .translate; + }, + .rotate => { + const allowed_prefixes = VendorPrefix{ .none = true }; + if (allowed_prefixes.contains(pre)) return .rotate; + }, + .scale => { + const allowed_prefixes = VendorPrefix{ .none = true }; + if (allowed_prefixes.contains(pre)) return .scale; + }, .@"text-decoration-color" => { const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true, .moz = true }; if (allowed_prefixes.contains(pre)) return .{ .@"text-decoration-color" = pre }; @@ -8363,6 +8936,10 @@ pub const PropertyId = union(PropertyIdTag) { const allowed_prefixes = VendorPrefix{ .none = true, .webkit = true }; if (allowed_prefixes.contains(pre)) return .{ .@"mask-box-image-repeat" = pre }; }, + .@"color-scheme" => { + const allowed_prefixes = VendorPrefix{ .none = true }; + if (allowed_prefixes.contains(pre)) return .@"color-scheme"; + }, } } @@ -8569,6 +9146,21 @@ pub const PropertyId = union(PropertyIdTag) { .@"font-variant-caps" => .@"font-variant-caps", .@"line-height" => .@"line-height", .font => .font, + .@"transition-property" => .{ .@"transition-property" = pre }, + .@"transition-duration" => .{ .@"transition-duration" = pre }, + .@"transition-delay" => .{ .@"transition-delay" = pre }, + .@"transition-timing-function" => .{ .@"transition-timing-function" = pre }, + .transition => .{ .transition = pre }, + .transform => .{ .transform = pre }, + .@"transform-origin" => .{ .@"transform-origin" = pre }, + .@"transform-style" => .{ .@"transform-style" = pre }, + .@"transform-box" => .@"transform-box", + .@"backface-visibility" => .{ .@"backface-visibility" = pre }, + .perspective => .{ .perspective = pre }, + .@"perspective-origin" => .{ .@"perspective-origin" = pre }, + .translate => .translate, + .rotate => .rotate, + .scale => .scale, .@"text-decoration-color" => .{ .@"text-decoration-color" = pre }, .@"text-emphasis-color" => .{ .@"text-emphasis-color" = pre }, .@"text-shadow" => .@"text-shadow", @@ -8601,6 +9193,7 @@ pub const PropertyId = union(PropertyIdTag) { .@"mask-box-image-width" => .{ .@"mask-box-image-width" = pre }, .@"mask-box-image-outset" => .{ .@"mask-box-image-outset" = pre }, .@"mask-box-image-repeat" => .{ .@"mask-box-image-repeat" = pre }, + .@"color-scheme" => .@"color-scheme", else => this.*, }; } @@ -8881,6 +9474,43 @@ pub const PropertyId = union(PropertyIdTag) { .@"font-variant-caps" => {}, .@"line-height" => {}, .font => {}, + .@"transition-property" => |*p| { + p.insert(pre); + }, + .@"transition-duration" => |*p| { + p.insert(pre); + }, + .@"transition-delay" => |*p| { + p.insert(pre); + }, + .@"transition-timing-function" => |*p| { + p.insert(pre); + }, + .transition => |*p| { + p.insert(pre); + }, + .transform => |*p| { + p.insert(pre); + }, + .@"transform-origin" => |*p| { + p.insert(pre); + }, + .@"transform-style" => |*p| { + p.insert(pre); + }, + .@"transform-box" => {}, + .@"backface-visibility" => |*p| { + p.insert(pre); + }, + .perspective => |*p| { + p.insert(pre); + }, + .@"perspective-origin" => |*p| { + p.insert(pre); + }, + .translate => {}, + .rotate => {}, + .scale => {}, .@"text-decoration-color" => |*p| { p.insert(pre); }, @@ -8945,6 +9575,7 @@ pub const PropertyId = union(PropertyIdTag) { .@"mask-box-image-repeat" => |*p| { p.insert(pre); }, + .@"color-scheme" => {}, else => {}, }; } @@ -8971,6 +9602,384 @@ pub const PropertyId = union(PropertyIdTag) { const tag = @intFromEnum(this.*); hasher.update(std.mem.asBytes(&tag)); } + + pub fn setPrefixesForTargets(this: *PropertyId, targets: Targets) void { + switch (this.*) { + .@"background-color" => {}, + .@"background-image" => {}, + .@"background-position-x" => {}, + .@"background-position-y" => {}, + .@"background-position" => {}, + .@"background-size" => {}, + .@"background-repeat" => {}, + .@"background-attachment" => {}, + .@"background-clip" => |*x| { + x.* = targets.prefixes(x.*, Feature.background_clip); + }, + + .@"background-origin" => {}, + .background => {}, + .@"box-shadow" => |*x| { + x.* = targets.prefixes(x.*, Feature.box_shadow); + }, + + .opacity => {}, + .color => {}, + .display => {}, + .visibility => {}, + .width => {}, + .height => {}, + .@"min-width" => {}, + .@"min-height" => {}, + .@"max-width" => {}, + .@"max-height" => {}, + .@"block-size" => {}, + .@"inline-size" => {}, + .@"min-block-size" => {}, + .@"min-inline-size" => {}, + .@"max-block-size" => {}, + .@"max-inline-size" => {}, + .@"box-sizing" => |*x| { + x.* = targets.prefixes(x.*, Feature.box_sizing); + }, + + .@"aspect-ratio" => {}, + .overflow => {}, + .@"overflow-x" => {}, + .@"overflow-y" => {}, + .@"text-overflow" => |*x| { + x.* = targets.prefixes(x.*, Feature.text_overflow); + }, + + .position => {}, + .top => {}, + .bottom => {}, + .left => {}, + .right => {}, + .@"inset-block-start" => {}, + .@"inset-block-end" => {}, + .@"inset-inline-start" => {}, + .@"inset-inline-end" => {}, + .@"inset-block" => {}, + .@"inset-inline" => {}, + .inset => {}, + .@"border-spacing" => {}, + .@"border-top-color" => {}, + .@"border-bottom-color" => {}, + .@"border-left-color" => {}, + .@"border-right-color" => {}, + .@"border-block-start-color" => {}, + .@"border-block-end-color" => {}, + .@"border-inline-start-color" => {}, + .@"border-inline-end-color" => {}, + .@"border-top-style" => {}, + .@"border-bottom-style" => {}, + .@"border-left-style" => {}, + .@"border-right-style" => {}, + .@"border-block-start-style" => {}, + .@"border-block-end-style" => {}, + .@"border-inline-start-style" => {}, + .@"border-inline-end-style" => {}, + .@"border-top-width" => {}, + .@"border-bottom-width" => {}, + .@"border-left-width" => {}, + .@"border-right-width" => {}, + .@"border-block-start-width" => {}, + .@"border-block-end-width" => {}, + .@"border-inline-start-width" => {}, + .@"border-inline-end-width" => {}, + .@"border-top-left-radius" => |*x| { + x.* = targets.prefixes(x.*, Feature.border_top_left_radius); + }, + + .@"border-top-right-radius" => |*x| { + x.* = targets.prefixes(x.*, Feature.border_top_right_radius); + }, + + .@"border-bottom-left-radius" => |*x| { + x.* = targets.prefixes(x.*, Feature.border_bottom_left_radius); + }, + + .@"border-bottom-right-radius" => |*x| { + x.* = targets.prefixes(x.*, Feature.border_bottom_right_radius); + }, + + .@"border-start-start-radius" => {}, + .@"border-start-end-radius" => {}, + .@"border-end-start-radius" => {}, + .@"border-end-end-radius" => {}, + .@"border-radius" => |*x| { + x.* = targets.prefixes(x.*, Feature.border_radius); + }, + + .@"border-image-source" => {}, + .@"border-image-outset" => {}, + .@"border-image-repeat" => {}, + .@"border-image-width" => {}, + .@"border-image-slice" => {}, + .@"border-image" => |*x| { + x.* = targets.prefixes(x.*, Feature.border_image); + }, + + .@"border-color" => {}, + .@"border-style" => {}, + .@"border-width" => {}, + .@"border-block-color" => {}, + .@"border-block-style" => {}, + .@"border-block-width" => {}, + .@"border-inline-color" => {}, + .@"border-inline-style" => {}, + .@"border-inline-width" => {}, + .border => {}, + .@"border-top" => {}, + .@"border-bottom" => {}, + .@"border-left" => {}, + .@"border-right" => {}, + .@"border-block" => {}, + .@"border-block-start" => {}, + .@"border-block-end" => {}, + .@"border-inline" => {}, + .@"border-inline-start" => {}, + .@"border-inline-end" => {}, + .outline => {}, + .@"outline-color" => {}, + .@"outline-style" => {}, + .@"outline-width" => {}, + .@"flex-direction" => |*x| { + x.* = targets.prefixes(x.*, Feature.flex_direction); + }, + + .@"flex-wrap" => |*x| { + x.* = targets.prefixes(x.*, Feature.flex_wrap); + }, + + .@"flex-flow" => |*x| { + x.* = targets.prefixes(x.*, Feature.flex_flow); + }, + + .@"flex-grow" => |*x| { + x.* = targets.prefixes(x.*, Feature.flex_grow); + }, + + .@"flex-shrink" => |*x| { + x.* = targets.prefixes(x.*, Feature.flex_shrink); + }, + + .@"flex-basis" => |*x| { + x.* = targets.prefixes(x.*, Feature.flex_basis); + }, + + .flex => |*x| { + x.* = targets.prefixes(x.*, Feature.flex); + }, + + .order => |*x| { + x.* = targets.prefixes(x.*, Feature.order); + }, + + .@"align-content" => |*x| { + x.* = targets.prefixes(x.*, Feature.align_content); + }, + + .@"justify-content" => |*x| { + x.* = targets.prefixes(x.*, Feature.justify_content); + }, + + .@"place-content" => {}, + .@"align-self" => |*x| { + x.* = targets.prefixes(x.*, Feature.align_self); + }, + + .@"justify-self" => {}, + .@"place-self" => {}, + .@"align-items" => |*x| { + x.* = targets.prefixes(x.*, Feature.align_items); + }, + + .@"justify-items" => {}, + .@"place-items" => {}, + .@"row-gap" => {}, + .@"column-gap" => {}, + .gap => {}, + .@"box-orient" => {}, + .@"box-direction" => {}, + .@"box-ordinal-group" => {}, + .@"box-align" => {}, + .@"box-flex" => {}, + .@"box-flex-group" => {}, + .@"box-pack" => {}, + .@"box-lines" => {}, + .@"flex-pack" => {}, + .@"flex-order" => {}, + .@"flex-align" => {}, + .@"flex-item-align" => {}, + .@"flex-line-pack" => {}, + .@"flex-positive" => {}, + .@"flex-negative" => {}, + .@"flex-preferred-size" => {}, + .@"margin-top" => {}, + .@"margin-bottom" => {}, + .@"margin-left" => {}, + .@"margin-right" => {}, + .@"margin-block-start" => {}, + .@"margin-block-end" => {}, + .@"margin-inline-start" => {}, + .@"margin-inline-end" => {}, + .@"margin-block" => {}, + .@"margin-inline" => {}, + .margin => {}, + .@"padding-top" => {}, + .@"padding-bottom" => {}, + .@"padding-left" => {}, + .@"padding-right" => {}, + .@"padding-block-start" => {}, + .@"padding-block-end" => {}, + .@"padding-inline-start" => {}, + .@"padding-inline-end" => {}, + .@"padding-block" => {}, + .@"padding-inline" => {}, + .padding => {}, + .@"scroll-margin-top" => {}, + .@"scroll-margin-bottom" => {}, + .@"scroll-margin-left" => {}, + .@"scroll-margin-right" => {}, + .@"scroll-margin-block-start" => {}, + .@"scroll-margin-block-end" => {}, + .@"scroll-margin-inline-start" => {}, + .@"scroll-margin-inline-end" => {}, + .@"scroll-margin-block" => {}, + .@"scroll-margin-inline" => {}, + .@"scroll-margin" => {}, + .@"scroll-padding-top" => {}, + .@"scroll-padding-bottom" => {}, + .@"scroll-padding-left" => {}, + .@"scroll-padding-right" => {}, + .@"scroll-padding-block-start" => {}, + .@"scroll-padding-block-end" => {}, + .@"scroll-padding-inline-start" => {}, + .@"scroll-padding-inline-end" => {}, + .@"scroll-padding-block" => {}, + .@"scroll-padding-inline" => {}, + .@"scroll-padding" => {}, + .@"font-weight" => {}, + .@"font-size" => {}, + .@"font-stretch" => {}, + .@"font-family" => {}, + .@"font-style" => {}, + .@"font-variant-caps" => {}, + .@"line-height" => {}, + .font => {}, + .@"transition-property" => |*x| { + x.* = targets.prefixes(x.*, Feature.transition_property); + }, + + .@"transition-duration" => |*x| { + x.* = targets.prefixes(x.*, Feature.transition_duration); + }, + + .@"transition-delay" => |*x| { + x.* = targets.prefixes(x.*, Feature.transition_delay); + }, + + .@"transition-timing-function" => |*x| { + x.* = targets.prefixes(x.*, Feature.transition_timing_function); + }, + + .transition => |*x| { + x.* = targets.prefixes(x.*, Feature.transition); + }, + + .transform => |*x| { + x.* = targets.prefixes(x.*, Feature.transform); + }, + + .@"transform-origin" => |*x| { + x.* = targets.prefixes(x.*, Feature.transform_origin); + }, + + .@"transform-style" => |*x| { + x.* = targets.prefixes(x.*, Feature.transform_style); + }, + + .@"transform-box" => {}, + .@"backface-visibility" => |*x| { + x.* = targets.prefixes(x.*, Feature.backface_visibility); + }, + + .perspective => |*x| { + x.* = targets.prefixes(x.*, Feature.perspective); + }, + + .@"perspective-origin" => |*x| { + x.* = targets.prefixes(x.*, Feature.perspective_origin); + }, + + .translate => {}, + .rotate => {}, + .scale => {}, + .@"text-decoration-color" => |*x| { + x.* = targets.prefixes(x.*, Feature.text_decoration_color); + }, + + .@"text-emphasis-color" => |*x| { + x.* = targets.prefixes(x.*, Feature.text_emphasis_color); + }, + + .@"text-shadow" => {}, + .direction => {}, + .composes => {}, + .@"mask-image" => |*x| { + x.* = targets.prefixes(x.*, Feature.mask_image); + }, + + .@"mask-mode" => {}, + .@"mask-repeat" => |*x| { + x.* = targets.prefixes(x.*, Feature.mask_repeat); + }, + + .@"mask-position-x" => {}, + .@"mask-position-y" => {}, + .@"mask-position" => |*x| { + x.* = targets.prefixes(x.*, Feature.mask_position); + }, + + .@"mask-clip" => |*x| { + x.* = targets.prefixes(x.*, Feature.mask_clip); + }, + + .@"mask-origin" => |*x| { + x.* = targets.prefixes(x.*, Feature.mask_origin); + }, + + .@"mask-size" => |*x| { + x.* = targets.prefixes(x.*, Feature.mask_size); + }, + + .@"mask-composite" => {}, + .@"mask-type" => {}, + .mask => |*x| { + x.* = targets.prefixes(x.*, Feature.mask); + }, + + .@"mask-border-source" => {}, + .@"mask-border-mode" => {}, + .@"mask-border-slice" => {}, + .@"mask-border-width" => {}, + .@"mask-border-outset" => {}, + .@"mask-border-repeat" => {}, + .@"mask-border" => {}, + .@"-webkit-mask-composite" => {}, + .@"mask-source-type" => {}, + .@"mask-box-image" => {}, + .@"mask-box-image-source" => {}, + .@"mask-box-image-slice" => {}, + .@"mask-box-image-width" => {}, + .@"mask-box-image-outset" => {}, + .@"mask-box-image-repeat" => {}, + .@"color-scheme" => {}, + else => {}, + } + } }; pub const PropertyIdTag = enum(u16) { @"background-color", @@ -9171,6 +10180,21 @@ pub const PropertyIdTag = enum(u16) { @"font-variant-caps", @"line-height", font, + @"transition-property", + @"transition-duration", + @"transition-delay", + @"transition-timing-function", + transition, + transform, + @"transform-origin", + @"transform-style", + @"transform-box", + @"backface-visibility", + perspective, + @"perspective-origin", + translate, + rotate, + scale, @"text-decoration-color", @"text-emphasis-color", @"text-shadow", @@ -9203,6 +10227,7 @@ pub const PropertyIdTag = enum(u16) { @"mask-box-image-width", @"mask-box-image-outset", @"mask-box-image-repeat", + @"color-scheme", all, unparsed, custom, @@ -9409,6 +10434,21 @@ pub const PropertyIdTag = enum(u16) { .@"font-variant-caps" => false, .@"line-height" => false, .font => false, + .@"transition-property" => true, + .@"transition-duration" => true, + .@"transition-delay" => true, + .@"transition-timing-function" => true, + .transition => true, + .transform => true, + .@"transform-origin" => true, + .@"transform-style" => true, + .@"transform-box" => false, + .@"backface-visibility" => true, + .perspective => true, + .@"perspective-origin" => true, + .translate => false, + .rotate => false, + .scale => false, .@"text-decoration-color" => true, .@"text-emphasis-color" => true, .@"text-shadow" => false, @@ -9441,6 +10481,7 @@ pub const PropertyIdTag = enum(u16) { .@"mask-box-image-width" => true, .@"mask-box-image-outset" => true, .@"mask-box-image-repeat" => true, + .@"color-scheme" => false, .unparsed => false, .custom => false, .all => false, @@ -9649,6 +10690,21 @@ pub const PropertyIdTag = enum(u16) { .@"font-variant-caps" => FontVariantCaps, .@"line-height" => LineHeight, .font => Font, + .@"transition-property" => SmallList(PropertyId, 1), + .@"transition-duration" => SmallList(Time, 1), + .@"transition-delay" => SmallList(Time, 1), + .@"transition-timing-function" => SmallList(EasingFunction, 1), + .transition => SmallList(Transition, 1), + .transform => TransformList, + .@"transform-origin" => Position, + .@"transform-style" => TransformStyle, + .@"transform-box" => TransformBox, + .@"backface-visibility" => BackfaceVisibility, + .perspective => Perspective, + .@"perspective-origin" => Position, + .translate => Translate, + .rotate => Rotate, + .scale => Scale, .@"text-decoration-color" => CssColor, .@"text-emphasis-color" => CssColor, .@"text-shadow" => SmallList(TextShadow, 1), @@ -9681,6 +10737,7 @@ pub const PropertyIdTag = enum(u16) { .@"mask-box-image-width" => Rect(BorderImageSideWidth), .@"mask-box-image-outset" => Rect(LengthOrNumber), .@"mask-box-image-repeat" => BorderImageRepeat, + .@"color-scheme" => ColorScheme, .all => CSSWideKeyword, .unparsed => UnparsedProperty, .custom => CustomProperty, diff --git a/src/css/properties/properties_impl.zig b/src/css/properties/properties_impl.zig index 871a61cdd32e8c..514578d6ecd17b 100644 --- a/src/css/properties/properties_impl.zig +++ b/src/css/properties/properties_impl.zig @@ -18,7 +18,7 @@ pub fn PropertyIdImpl() type { return struct { pub fn toCss(this: *const PropertyId, comptime W: type, dest: *Printer(W)) PrintErr!void { var first = true; - const name = this.name(this); + const name = this.name(); const prefix_value = this.prefix().orNone(); inline for (VendorPrefix.FIELDS) |field| { diff --git a/src/css/properties/transform.zig b/src/css/properties/transform.zig index 8a1c879798b35e..0beb971e7342ac 100644 --- a/src/css/properties/transform.zig +++ b/src/css/properties/transform.zig @@ -9,6 +9,9 @@ const SmallList = css.SmallList; const Printer = css.Printer; const PrintErr = css.PrintErr; const Result = css.Result; +const VendorPrefix = css.VendorPrefix; +const PropertyId = css.css_properties.PropertyId; +const Property = css.css_properties.Property; const ContainerName = css.css_rules.container.ContainerName; @@ -86,6 +89,8 @@ pub const TransformList = struct { return dest.writeStr(base.items); } + + return this.toCssBase(W, dest); } fn toCssBase(this: *const @This(), comptime W: type, dest: *Printer(W)) PrintErr!void { @@ -97,6 +102,10 @@ pub const TransformList = struct { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }; /// An individual transform function (https://www.w3.org/TR/2019/CR-css-transforms-1-20190214/#two-d-transform-functions). @@ -109,6 +118,10 @@ pub const Transform = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A translation in the X direction. translate_x: LengthPercentage, @@ -125,6 +138,10 @@ pub const Transform = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A 2D scale. scale: struct { @@ -134,6 +151,10 @@ pub const Transform = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A scale in the X direction. scale_x: NumberOrPercentage, @@ -150,6 +171,10 @@ pub const Transform = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A 2D rotation. rotate: Angle, @@ -166,6 +191,10 @@ pub const Transform = union(enum) { z: f32, angle: Angle, + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } @@ -178,6 +207,10 @@ pub const Transform = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A skew along the X axis. skew_x: Angle, @@ -773,6 +806,10 @@ pub const Transform = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }; /// A 2D matrix. @@ -814,17 +851,43 @@ pub fn Matrix3d(comptime T: type) type { m42: T, m43: T, m44: T, + + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } }; } /// A value for the [transform-style](https://drafts.csswg.org/css-transforms-2/#transform-style-property) property. -pub const TransformStyle = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const TransformStyle = enum { + flat, + @"preserve-3d", + pub usingnamespace css.DefineEnumProperty(@This()); +}; /// A value for the [transform-box](https://drafts.csswg.org/css-transforms-1/#transform-box) property. -pub const TransformBox = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const TransformBox = enum { + /// Uses the content box as reference box. + @"content-box", + /// Uses the border box as reference box. + @"border-box", + /// Uses the object bounding box as reference box. + @"fill-box", + /// Uses the stroke bounding box as reference box. + @"stroke-box", + /// Uses the nearest SVG viewport as reference box. + @"view-box", + + pub usingnamespace css.DefineEnumProperty(@This()); +}; /// A value for the [backface-visibility](https://drafts.csswg.org/css-transforms-2/#backface-visibility-property) property. -pub const BackfaceVisibility = css.DefineEnumProperty(@compileError(css.todo_stuff.depth)); +pub const BackfaceVisibility = enum { + visible, + hidden, + + pub usingnamespace css.DefineEnumProperty(@This()); +}; /// A value for the perspective property. pub const Perspective = union(enum) { @@ -832,6 +895,17 @@ pub const Perspective = union(enum) { none, /// Distance to the center of projection. length: Length, + + pub usingnamespace css.DeriveParse(@This()); + pub usingnamespace css.DeriveToCss(@This()); + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } + + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } }; /// A value for the [translate](https://drafts.csswg.org/css-transforms-2/#propdef-translate) property. @@ -847,7 +921,77 @@ pub const Translate = union(enum) { y: LengthPercentage, /// The z translation. z: Length, + + pub fn __generateDeepClone() void {} + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, + + pub fn parse(input: *css.Parser) css.Result(@This()) { + if (input.tryParse(css.Parser.expectIdentMatching, .{"none"}).isOk()) { + return .{ .result = .none }; + } + + const x = switch (LengthPercentage.parse(input)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + const y = input.tryParse(LengthPercentage.parse, .{}); + const z = if (y.isOk()) input.tryParse(Length.parse, .{}).asValue() else null; + + return .{ + .result = Translate{ + .xyz = .{ + .x = x, + .y = y.unwrapOr(comptime LengthPercentage.zero()), + .z = z orelse Length.zero(), + }, + }, + }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) PrintErr!void { + switch (this.*) { + .none => try dest.writeStr("none"), + .xyz => |xyz| { + try xyz.x.toCss(W, dest); + if (!xyz.y.isZero() or !xyz.z.isZero()) { + try dest.writeChar(' '); + try xyz.y.toCss(W, dest); + if (!xyz.z.isZero()) { + try dest.writeChar(' '); + try xyz.z.toCss(W, dest); + } + } + }, + } + return; + } + + pub fn toTransform(this: *const @This(), allocator: std.mem.Allocator) Transform { + return switch (this.*) { + .none => .{ .translate_3d = .{ + .x = LengthPercentage.zero(), + .y = LengthPercentage.zero(), + .z = Length.zero(), + } }, + .xyz => |xyz| .{ .translate_3d = .{ + .x = xyz.x.deepClone(allocator), + .y = xyz.y.deepClone(allocator), + .z = xyz.z.deepClone(allocator), + } }, + }; + } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } + + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } }; /// A value for the [rotate](https://drafts.csswg.org/css-transforms-2/#propdef-rotate) property. @@ -860,6 +1004,112 @@ pub const Rotate = struct { z: f32, /// The angle of rotation. angle: Angle, + + pub fn parse(input: *css.Parser) css.Result(@This()) { + if (input.tryParse(css.Parser.expectIdentMatching, .{"none"}).isOk()) { + return .{ .result = .{ + .x = 0.0, + .y = 0.0, + .z = 1.0, + .angle = .{ .deg = 0.0 }, + } }; + } + + const angle = input.tryParse(Angle.parse, .{}); + + const XYZ = struct { x: f32, y: f32, z: f32 }; + const xyz = switch (input.tryParse(struct { + fn parse(i: *css.Parser) css.Result(XYZ) { + const location = i.currentSourceLocation(); + const ident = switch (i.expectIdent()) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "x")) { + return .{ .result = .{ .x = 1.0, .y = 0.0, .z = 0.0 } }; + } else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "y")) { + return .{ .result = .{ .x = 0.0, .y = 1.0, .z = 0.0 } }; + } else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "z")) { + return .{ .result = .{ .x = 0.0, .y = 0.0, .z = 1.0 } }; + } + return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) }; + } + }.parse, .{})) { + .result => |v| v, + .err => input.tryParse(struct { + fn parse(i: *css.Parser) css.Result(XYZ) { + const x = switch (css.CSSNumberFns.parse(i)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + const y = switch (css.CSSNumberFns.parse(i)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + const z = switch (css.CSSNumberFns.parse(i)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + return .{ .result = .{ .x = x, .y = y, .z = z } }; + } + }.parse, .{}).unwrapOr(.{ .x = 0.0, .y = 0.0, .z = 1.0 }), + }; + + const final_angle = switch (angle) { + .result => |v| v, + .err => switch (Angle.parse(input)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }, + }; + + return .{ .result = .{ + .x = xyz.x, + .y = xyz.y, + .z = xyz.z, + .angle = final_angle, + } }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) PrintErr!void { + if (this.x == 0.0 and this.y == 0.0 and this.z == 1.0 and this.angle.isZero()) { + try dest.writeStr("none"); + return; + } + + if (this.x == 1.0 and this.y == 0.0 and this.z == 0.0) { + try dest.writeStr("x "); + } else if (this.x == 0.0 and this.y == 1.0 and this.z == 0.0) { + try dest.writeStr("y "); + } else if (!(this.x == 0.0 and this.y == 0.0 and this.z == 1.0)) { + try css.CSSNumberFns.toCss(&this.x, W, dest); + try dest.writeChar(' '); + try css.CSSNumberFns.toCss(&this.y, W, dest); + try dest.writeChar(' '); + try css.CSSNumberFns.toCss(&this.z, W, dest); + try dest.writeChar(' '); + } + + try this.angle.toCss(W, dest); + } + + /// Converts the rotation to a transform function. + pub fn toTransform(this: *const @This(), allocator: std.mem.Allocator) Transform { + return .{ .rotate_3d = .{ + .x = this.x, + .y = this.y, + .z = this.z, + .angle = this.angle.deepClone(allocator), + } }; + } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } + + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } }; /// A value for the [scale](https://drafts.csswg.org/css-transforms-2/#propdef-scale) property. @@ -875,5 +1125,178 @@ pub const Scale = union(enum) { y: NumberOrPercentage, /// Scale on the z axis. z: NumberOrPercentage, + + pub fn __generateDeepClone() void {} + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, + + pub fn parse(input: *css.Parser) css.Result(@This()) { + if (input.tryParse(css.Parser.expectIdentMatching, .{"none"}).isOk()) { + return .{ .result = .none }; + } + + const x = switch (NumberOrPercentage.parse(input)) { + .result => |v| v, + .err => |e| return .{ .err = e }, + }; + + const y = input.tryParse(NumberOrPercentage.parse, .{}); + const z = if (y.isOk()) input.tryParse(NumberOrPercentage.parse, .{}).asValue() else null; + + return .{ .result = .{ .xyz = .{ + .x = x, + .y = if (y.asValue()) |val| val else x, + .z = if (z) |val| val else .{ .number = 1.0 }, + } } }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *css.Printer(W)) PrintErr!void { + switch (this.*) { + .none => try dest.writeStr("none"), + .xyz => |xyz| { + try xyz.x.toCss(W, dest); + const z_val = xyz.z.intoF32(); + if (!xyz.y.eql(&xyz.x) or z_val != 1.0) { + try dest.writeChar(' '); + try xyz.y.toCss(W, dest); + if (z_val != 1.0) { + try dest.writeChar(' '); + try xyz.z.toCss(W, dest); + } + } + }, + } + } + + pub fn toTransform(this: *const @This(), allocator: std.mem.Allocator) Transform { + return switch (this.*) { + .none => .{ .scale_3d = .{ + .x = .{ .number = 1.0 }, + .y = .{ .number = 1.0 }, + .z = .{ .number = 1.0 }, + } }, + .xyz => |xyz| .{ .scale_3d = .{ + .x = xyz.x.deepClone(allocator), + .y = xyz.y.deepClone(allocator), + .z = xyz.z.deepClone(allocator), + } }, + }; + } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } + + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } +}; + +pub const TransformHandler = struct { + transform: ?struct { TransformList, VendorPrefix } = null, + translate: ?Translate = null, + rotate: ?Rotate = null, + scale: ?Scale = null, + has_any: bool = false, + + pub fn handleProperty( + this: *@This(), + property: *const css.Property, + dest: *css.DeclarationList, + context: *css.PropertyHandlerContext, + ) bool { + const individualProperty = struct { + fn individualProperty(self: *TransformHandler, allocator: std.mem.Allocator, comptime field: []const u8, val: anytype) void { + if (self.transform) |*transform| { + transform.*[0].v.append(allocator, val.toTransform(allocator)) catch bun.outOfMemory(); + } else { + @field(self, field) = val.deepClone(allocator); + self.has_any = true; + } + } + }.individualProperty; + const allocator = context.allocator; + + switch (property.*) { + .transform => |val| { + const transform_val = val[0]; + const vp = val[1]; + + // If two vendor prefixes for the same property have different + // values, we need to flush what we have immediately to preserve order. + if (this.transform) |current| { + if (!current[0].eql(&transform_val) and !current[1].contains(vp)) { + this.flush(allocator, dest, context); + } + } + + // Otherwise, update the value and add the prefix. + if (this.transform) |*transform| { + transform.* = .{ transform_val.deepClone(allocator), transform.*[1].bitwiseOr(vp) }; + } else { + this.transform = .{ transform_val.deepClone(allocator), vp }; + this.has_any = true; + } + + this.translate = null; + this.rotate = null; + this.scale = null; + }, + .translate => |val| individualProperty(this, allocator, "translate", val), + .rotate => |val| individualProperty(this, allocator, "rotate", val), + .scale => |val| individualProperty(this, allocator, "scale", val), + .unparsed => |unparsed| { + if (unparsed.property_id == .transform or + unparsed.property_id == .translate or + unparsed.property_id == .rotate or + unparsed.property_id == .scale) + { + this.flush(allocator, dest, context); + const prop = if (unparsed.property_id == .transform) + Property{ .unparsed = unparsed.getPrefixed(allocator, context.targets, css.prefixes.Feature.transform) } + else + property.deepClone(allocator); + dest.append(allocator, prop) catch bun.outOfMemory(); + } else return false; + }, + else => return false, + } + + return true; + } + + pub fn finalize(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + this.flush(context.allocator, dest, context); + } + + fn flush(this: *@This(), allocator: std.mem.Allocator, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + if (!this.has_any) return; + + this.has_any = false; + + const transform = bun.take(&this.transform); + const translate = bun.take(&this.translate); + const rotate = bun.take(&this.rotate); + const scale = bun.take(&this.scale); + + if (transform) |t| { + const prefix = context.targets.prefixes(t[1], css.prefixes.Feature.transform); + dest.append(allocator, Property{ .transform = .{ t[0], prefix } }) catch bun.outOfMemory(); + } + + if (translate) |t| { + dest.append(allocator, Property{ .translate = t }) catch bun.outOfMemory(); + } + + if (rotate) |r| { + dest.append(allocator, Property{ .rotate = r }) catch bun.outOfMemory(); + } + + if (scale) |s| { + dest.append(allocator, Property{ .scale = s }) catch bun.outOfMemory(); + } + } }; diff --git a/src/css/properties/transition.zig b/src/css/properties/transition.zig index a44aa5cc11d6de..c2acd1a3fd923c 100644 --- a/src/css/properties/transition.zig +++ b/src/css/properties/transition.zig @@ -33,5 +33,515 @@ const Percentage = css.css_values.percentage.Percentage; const GenericBorder = css.css_properties.border.GenericBorder; const LineStyle = css.css_properties.border.LineStyle; +const Property = css.css_properties.Property; +const PropertyId = css.css_properties.PropertyId; +const Time = css.css_values.time.Time; +const EasingFunction = css.css_values.easing.EasingFunction; + +const VendorPrefix = css.VendorPrefix; +const Feature = css.prefixes.Feature; + /// A value for the [transition](https://www.w3.org/TR/2018/WD-css-transitions-1-20181011/#transition-shorthand-property) property. -pub const Transition = @compileError(css.todo_stuff.depth); +pub const Transition = struct { + /// The property to transition. + property: PropertyId, + /// The duration of the transition. + duration: Time, + /// The delay before the transition starts. + delay: Time, + /// The easing function for the transition. + timing_function: EasingFunction, + + pub usingnamespace css.DefineShorthand(@This(), css.PropertyIdTag.transition, PropertyFieldMap); + pub usingnamespace css.DefineListShorthand(@This()); + + pub const PropertyFieldMap = .{ + .property = css.PropertyIdTag.@"transition-property", + .duration = css.PropertyIdTag.@"transition-duration", + .delay = css.PropertyIdTag.@"transition-delay", + .timing_function = css.PropertyIdTag.@"transition-timing-function", + }; + + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } + + pub fn deepClone(this: *const @This(), allocator: Allocator) @This() { + return css.implementDeepClone(comptime @This(), this, allocator); + } + + pub fn parse(parser: *css.Parser) css.Result(@This()) { + var property: ?PropertyId = null; + var duration: ?Time = null; + var delay: ?Time = null; + var timing_function: ?EasingFunction = null; + + while (true) { + if (duration == null) { + if (parser.tryParse(Time.parse, .{}).asValue()) |value| { + duration = value; + continue; + } + } + + if (timing_function == null) { + if (parser.tryParse(EasingFunction.parse, .{}).asValue()) |value| { + timing_function = value; + continue; + } + } + + if (delay == null) { + if (parser.tryParse(Time.parse, .{}).asValue()) |value| { + delay = value; + continue; + } + } + + if (property == null) { + if (parser.tryParse(PropertyId.parse, .{}).asValue()) |value| { + property = value; + continue; + } + } + + break; + } + + return .{ .result = .{ + .property = property orelse .all, + .duration = duration orelse .{ .seconds = 0.0 }, + .delay = delay orelse .{ .seconds = 0.0 }, + .timing_function = timing_function orelse .ease, + } }; + } + + pub fn toCss(this: *const @This(), comptime W: type, dest: *Printer(W)) PrintErr!void { + try this.property.toCss(W, dest); + if (!this.duration.isZero() or !this.delay.isZero()) { + try dest.writeChar(' '); + try this.duration.toCss(W, dest); + } + + if (!this.timing_function.isEase()) { + try dest.writeChar(' '); + try this.timing_function.toCss(W, dest); + } + + if (!this.delay.isZero()) { + try dest.writeChar(' '); + try this.delay.toCss(W, dest); + } + } +}; + +pub const TransitionHandler = struct { + properties: ?struct { SmallList(PropertyId, 1), VendorPrefix } = null, + durations: ?struct { SmallList(Time, 1), VendorPrefix } = null, + delays: ?struct { SmallList(Time, 1), VendorPrefix } = null, + timing_functions: ?struct { SmallList(EasingFunction, 1), VendorPrefix } = null, + has_any: bool = false, + + pub fn handleProperty(this: *@This(), prop: *const Property, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) bool { + switch (prop.*) { + .@"transition-property" => |*x| this.property(dest, context, Feature.transition_property, "properties", &x.*[0], x.*[1]), + .@"transition-duration" => |*x| this.property(dest, context, Feature.transition_duration, "durations", &x.*[0], x.*[1]), + .@"transition-delay" => |*x| this.property(dest, context, Feature.transition_delay, "delays", &x.*[0], x.*[1]), + .@"transition-timing-function" => |*x| this.property(dest, context, Feature.transition_timing_function, "timing_functions", &x.*[0], x.*[1]), + .transition => |*x| { + const val: *const SmallList(Transition, 1) = &x.*[0]; + const vp: VendorPrefix = x.*[1]; + + var properties = SmallList(PropertyId, 1).initCapacity(context.allocator, val.len()); + var durations = SmallList(Time, 1).initCapacity(context.allocator, val.len()); + var delays = SmallList(Time, 1).initCapacity(context.allocator, val.len()); + var timing_functions = SmallList(EasingFunction, 1).initCapacity(context.allocator, val.len()); + properties.setLen(val.len()); + durations.setLen(val.len()); + delays.setLen(val.len()); + timing_functions.setLen(val.len()); + + for (val.slice(), properties.slice_mut()) |*item, *out_prop| { + out_prop.* = item.property.deepClone(context.allocator); + } + this.maybeFlush(dest, context, "properties", &properties, vp); + + for (val.slice(), durations.slice_mut()) |*item, *out_dur| { + out_dur.* = item.duration.deepClone(context.allocator); + } + this.maybeFlush(dest, context, "durations", &durations, vp); + + for (val.slice(), delays.slice_mut()) |*item, *out_delay| { + out_delay.* = item.delay.deepClone(context.allocator); + } + this.maybeFlush(dest, context, "delays", &delays, vp); + + for (val.slice(), timing_functions.slice_mut()) |*item, *out_timing| { + out_timing.* = item.timing_function.deepClone(context.allocator); + } + this.maybeFlush(dest, context, "timing_functions", &timing_functions, vp); + + this.property(dest, context, Feature.transition_property, "properties", &properties, vp); + this.property(dest, context, Feature.transition_duration, "durations", &durations, vp); + this.property(dest, context, Feature.transition_delay, "delays", &delays, vp); + this.property(dest, context, Feature.transition_timing_function, "timing_functions", &timing_functions, vp); + }, + .unparsed => |*x| if (isTransitionProperty(&x.property_id)) { + this.flush(dest, context); + dest.append( + context.allocator, + .{ .unparsed = x.getPrefixed(context.allocator, context.targets, Feature.transition) }, + ) catch bun.outOfMemory(); + } else return false, + else => return false, + } + + return true; + } + + pub fn finalize(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + this.flush(dest, context); + } + + fn property(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime feature: Feature, comptime prop: []const u8, val: anytype, vp: VendorPrefix) void { + this.maybeFlush(dest, context, prop, val, vp); + + // Otherwise, update the value and add the prefix. + if (@field(this, prop)) |*p| { + const v = &p.*[0]; + const prefixes = &p.*[1]; + v.* = val.deepClone(context.allocator); + prefixes.insert(vp); + prefixes.* = context.targets.prefixes(prefixes.*, feature); + } else { + const prefixes = context.targets.prefixes(vp, feature); + const cloned_val = val.deepClone(context.allocator); + @field(this, prop) = .{ cloned_val, prefixes }; + this.has_any = true; + } + } + + fn maybeFlush(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, val: anytype, vp: VendorPrefix) void { + // If two vendor prefixes for the same property have different + // values, we need to flush what we have immediately to preserve order. + if (@field(this, prop)) |*p| { + const v = &p.*[0]; + const prefixes = &p.*[1]; + if (!val.eql(v) and !prefixes.contains(vp)) { + this.flush(dest, context); + } + } + } + + fn flush(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void { + if (!this.has_any) return; + this.has_any = false; + + var _properties: ?struct { SmallList(PropertyId, 1), VendorPrefix } = bun.take(&this.properties); + var _durations: ?struct { SmallList(Time, 1), VendorPrefix } = bun.take(&this.durations); + var _delays: ?struct { SmallList(Time, 1), VendorPrefix } = bun.take(&this.delays); + var _timing_functions: ?struct { SmallList(EasingFunction, 1), VendorPrefix } = bun.take(&this.timing_functions); + + var rtl_properties: ?SmallList(PropertyId, 1) = if (_properties) |*p| expandProperties(&p.*[0], context) else null; + + if (_properties != null and _durations != null and _delays != null and _timing_functions != null) { + const properties: *SmallList(PropertyId, 1) = &_properties.?[0]; + const property_prefixes: *VendorPrefix = &_properties.?[1]; + const durations: *SmallList(Time, 1) = &_durations.?[0]; + const duration_prefixes: *VendorPrefix = &_durations.?[1]; + const delays: *SmallList(Time, 1) = &_delays.?[0]; + const delay_prefixes: *VendorPrefix = &_delays.?[1]; + const timing_functions: *SmallList(EasingFunction, 1) = &_timing_functions.?[0]; + const timing_prefixes: *VendorPrefix = &_timing_functions.?[1]; + + // Find the intersection of prefixes with the same value. + // Remove that from the prefixes of each of the properties. The remaining + // prefixes will be handled by outputting individual properties below. + const intersection = property_prefixes.bitwiseAnd(duration_prefixes.*).bitwiseAnd(delay_prefixes.*).bitwiseAnd(timing_prefixes.*); + if (!intersection.isEmpty()) { + const transitions = getTransitions(context, properties, durations, delays, timing_functions); + + if (rtl_properties) |*rtl_properties2| { + const rtl_transitions = getTransitions(context, rtl_properties2, durations, delays, timing_functions); + context.addLogicalRule( + context.allocator, + Property{ + .transition = .{ transitions, intersection }, + }, + Property{ + .transition = .{ rtl_transitions, intersection }, + }, + ); + } else { + dest.append( + context.allocator, + Property{ .transition = .{ transitions.deepClone(context.allocator), intersection } }, + ) catch bun.outOfMemory(); + } + + property_prefixes.remove(intersection); + duration_prefixes.remove(intersection); + delay_prefixes.remove(intersection); + timing_prefixes.remove(intersection); + } + } + + if (_properties != null) { + const properties: SmallList(PropertyId, 1) = _properties.?[0]; + const prefix: VendorPrefix = _properties.?[1]; + _properties = null; + if (!prefix.isEmpty()) { + if (rtl_properties) |rtl_properties2| { + context.addLogicalRule( + context.allocator, + Property{ .@"transition-property" = .{ properties, prefix } }, + Property{ .@"transition-property" = .{ rtl_properties2, prefix } }, + ); + rtl_properties = null; + } else { + dest.append(context.allocator, Property{ .@"transition-property" = .{ properties, prefix } }) catch bun.outOfMemory(); + } + } + } + + if (_durations != null) { + const durations: SmallList(Time, 1) = _durations.?[0]; + const prefix: VendorPrefix = _durations.?[1]; + _durations = null; + if (!prefix.isEmpty()) { + dest.append(context.allocator, Property{ .@"transition-duration" = .{ durations, prefix } }) catch bun.outOfMemory(); + } + } + + if (_delays != null) { + const delays: SmallList(Time, 1) = _delays.?[0]; + const prefix: VendorPrefix = _delays.?[1]; + _delays = null; + if (!prefix.isEmpty()) { + dest.append(context.allocator, Property{ .@"transition-delay" = .{ delays, prefix } }) catch bun.outOfMemory(); + } + } + + if (_timing_functions != null) { + const timing_functions: SmallList(EasingFunction, 1) = _timing_functions.?[0]; + const prefix: VendorPrefix = _timing_functions.?[1]; + _timing_functions = null; + if (!prefix.isEmpty()) { + dest.append(context.allocator, Property{ .@"transition-timing-function" = .{ timing_functions, prefix } }) catch bun.outOfMemory(); + } + } + + this.reset(); + } + + inline fn getTransitions( + context: *const css.PropertyHandlerContext, + properties: *SmallList(PropertyId, 1), + durations: *SmallList(Time, 1), + delays: *SmallList(Time, 1), + timing_functions: *SmallList(EasingFunction, 1), + ) SmallList(Transition, 1) { + const cycleBump = struct { + inline fn cycleBump(idx: *u32, len: u32) void { + idx.* = (idx.* + 1) % len; + } + }.cycleBump; + + // transition-property determines the number of transitions. The values of other + // properties are repeated to match this length. + var transitions = SmallList(Transition, 1).initCapacity(context.allocator, 1); + var durations_idx: u32 = 0; + var delays_idx: u32 = 0; + var timing_idx: u32 = 0; + for (properties.slice()) |*property_id| { + const duration = if (durations.len() > durations_idx) durations.at(durations_idx).deepClone(context.allocator) else Time{ .seconds = 0.0 }; + const delay = if (delays.len() > delays_idx) delays.at(delays_idx).deepClone(context.allocator) else Time{ .seconds = 0.0 }; + const timing_function = if (timing_functions.len() > timing_idx) timing_functions.at(timing_idx).deepClone(context.allocator) else EasingFunction.ease; + cycleBump(&durations_idx, durations.len()); + cycleBump(&delays_idx, delays.len()); + cycleBump(&timing_idx, timing_functions.len()); + const transition = Transition{ + .property = property_id.deepClone(context.allocator), + .duration = duration, + .delay = delay, + .timing_function = timing_function, + }; + var cloned = false; + + const prefix_to_iter = property_id.prefix().orNone(); + // Expand vendor prefixes into multiple transitions. + inline for (VendorPrefix.FIELDS) |prefix_field| { + if (@field(prefix_to_iter, prefix_field)) { + var t = if (cloned) transition.deepClone(context.allocator) else transition; + cloned = true; + var new_prefix = VendorPrefix{}; + @field(new_prefix, prefix_field) = true; + t.property = property_id.withPrefix(new_prefix); + transitions.append(context.allocator, t); + } + } + } + return transitions; + } + + pub fn reset(this: *@This()) void { + this.properties = null; + this.durations = null; + this.delays = null; + this.timing_functions = null; + this.has_any = false; + } +}; + +fn expandProperties(properties: *css.SmallList(PropertyId, 1), context: *css.PropertyHandlerContext) ?SmallList(PropertyId, 1) { + const replace = struct { + inline fn replace(allocator: Allocator, propertiez: anytype, props: []const PropertyId, i: u32) void { + propertiez.mut(i).* = props[0].deepClone(allocator); + if (props.len > 1) { + propertiez.insertSlice(allocator, i + 1, props[1..]); + } + } + }.replace; + + var rtl_properties: ?SmallList(PropertyId, 1) = null; + var i: u32 = 0; + + // Expand logical properties in place. + while (i < properties.len()) { + const result = getLogicalProperties(properties.at(i)); + if (result == .block and context.shouldCompileLogical(result.block[0])) { + replace(context.allocator, properties, result.block[1], i); + if (rtl_properties) |*rtl| { + replace(context.allocator, rtl, result.block[1], i); + } + i += 1; + } else if (result == .@"inline" and context.shouldCompileLogical(result.@"inline"[0])) { + const ltr = result.@"inline"[1]; + const rtl = result.@"inline"[2]; + // Clone properties to create RTL version only when needed. + if (rtl_properties == null) { + rtl_properties = properties.deepClone(context.allocator); + } + + replace(context.allocator, properties, ltr, i); + if (rtl_properties) |*rtl_props| { + replace(context.allocator, rtl_props, rtl, i); + } + + i += @intCast(ltr.len); + } else { + // Expand vendor prefixes for targets. + properties.mut(i).setPrefixesForTargets(context.targets); + + // Expand mask properties, which use different vendor-prefixed names. + if (css.css_properties.masking.getWebkitMaskProperty(properties.at(i))) |property_id| { + if (context.targets.prefixes(VendorPrefix.NONE, Feature.mask_border).contains(VendorPrefix.WEBKIT)) { + properties.insert(context.allocator, i, property_id); + i += 1; + } + } + + if (rtl_properties) |*rtl_props| { + rtl_props.mut(i).setPrefixesForTargets(context.targets); + + if (css.css_properties.masking.getWebkitMaskProperty(rtl_props.at(i))) |property_id| { + if (context.targets.prefixes(VendorPrefix.NONE, Feature.mask_border).contains(VendorPrefix.WEBKIT)) { + rtl_props.insert(context.allocator, i, property_id); + i += 1; + } + } + } + i += 1; + } + } + + return rtl_properties; +} + +const LogicalPropertyId = union(enum) { + none, + block: struct { css.compat.Feature, []const PropertyId }, + @"inline": struct { css.compat.Feature, []const PropertyId, []const PropertyId }, +}; + +fn getLogicalProperties(property_id: *const PropertyId) LogicalPropertyId { + return switch (property_id.*) { + .@"block-size" => .{ .block = .{ .logical_size, &[_]PropertyId{.height} } }, + .@"inline-size" => .{ .@"inline" = .{ .logical_size, &[_]PropertyId{.width}, &[_]PropertyId{.height} } }, + .@"min-block-size" => .{ .block = .{ .logical_size, &[_]PropertyId{.@"min-height"} } }, + .@"max-block-size" => .{ .block = .{ .logical_size, &[_]PropertyId{.@"max-height"} } }, + .@"min-inline-size" => .{ .@"inline" = .{ .logical_size, &[_]PropertyId{.@"min-width"}, &[_]PropertyId{.@"min-height"} } }, + .@"max-inline-size" => .{ .@"inline" = .{ .logical_size, &[_]PropertyId{.@"max-width"}, &[_]PropertyId{.@"max-height"} } }, + + .@"inset-block-start" => .{ .block = .{ .logical_inset, &[_]PropertyId{.top} } }, + .@"inset-block-end" => .{ .block = .{ .logical_inset, &[_]PropertyId{.bottom} } }, + .@"inset-inline-start" => .{ .@"inline" = .{ .logical_inset, &[_]PropertyId{.left}, &[_]PropertyId{.right} } }, + .@"inset-inline-end" => .{ .@"inline" = .{ .logical_inset, &[_]PropertyId{.right}, &[_]PropertyId{.left} } }, + .@"inset-block" => .{ .block = .{ .logical_inset, &[_]PropertyId{ .top, .bottom } } }, + .@"inset-inline" => .{ .block = .{ .logical_inset, &[_]PropertyId{ .left, .right } } }, + .inset => .{ .block = .{ .logical_inset, &[_]PropertyId{ .top, .bottom, .left, .right } } }, + + .@"margin-block-start" => .{ .block = .{ .logical_margin, &[_]PropertyId{.@"margin-top"} } }, + .@"margin-block-end" => .{ .block = .{ .logical_margin, &[_]PropertyId{.@"margin-bottom"} } }, + .@"margin-inline-start" => .{ .@"inline" = .{ .logical_margin, &[_]PropertyId{.@"margin-left"}, &[_]PropertyId{.@"margin-right"} } }, + .@"margin-inline-end" => .{ .@"inline" = .{ .logical_margin, &[_]PropertyId{.@"margin-right"}, &[_]PropertyId{.@"margin-left"} } }, + .@"margin-block" => .{ .block = .{ .logical_margin, &[_]PropertyId{ .@"margin-top", .@"margin-bottom" } } }, + .@"margin-inline" => .{ .block = .{ .logical_margin, &[_]PropertyId{ .@"margin-left", .@"margin-right" } } }, + + .@"padding-block-start" => .{ .block = .{ .logical_padding, &[_]PropertyId{.@"padding-top"} } }, + .@"padding-block-end" => .{ .block = .{ .logical_padding, &[_]PropertyId{.@"padding-bottom"} } }, + .@"padding-inline-start" => .{ .@"inline" = .{ .logical_padding, &[_]PropertyId{.@"padding-left"}, &[_]PropertyId{.@"padding-right"} } }, + .@"padding-inline-end" => .{ .@"inline" = .{ .logical_padding, &[_]PropertyId{.@"padding-right"}, &[_]PropertyId{.@"padding-left"} } }, + .@"padding-block" => .{ .block = .{ .logical_padding, &[_]PropertyId{ .@"padding-top", .@"padding-bottom" } } }, + .@"padding-inline" => .{ .block = .{ .logical_padding, &[_]PropertyId{ .@"padding-left", .@"padding-right" } } }, + + .@"border-block-start" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-top"} } }, + .@"border-block-start-width" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-top-width"} } }, + .@"border-block-start-color" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-top-color"} } }, + .@"border-block-start-style" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-top-style"} } }, + + .@"border-block-end" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-bottom"} } }, + .@"border-block-end-width" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-bottom-width"} } }, + .@"border-block-end-color" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-bottom-color"} } }, + .@"border-block-end-style" => .{ .block = .{ .logical_borders, &[_]PropertyId{.@"border-bottom-style"} } }, + + .@"border-inline-start" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-left"}, &[_]PropertyId{.@"border-right"} } }, + .@"border-inline-start-width" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-left-width"}, &[_]PropertyId{.@"border-right-width"} } }, + .@"border-inline-start-color" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-left-color"}, &[_]PropertyId{.@"border-right-color"} } }, + .@"border-inline-start-style" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-left-style"}, &[_]PropertyId{.@"border-right-style"} } }, + + .@"border-inline-end" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-right"}, &[_]PropertyId{.@"border-left"} } }, + .@"border-inline-end-width" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-right-width"}, &[_]PropertyId{.@"border-left-width"} } }, + .@"border-inline-end-color" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-right-color"}, &[_]PropertyId{.@"border-left-color"} } }, + .@"border-inline-end-style" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{.@"border-right-style"}, &[_]PropertyId{.@"border-left-style"} } }, + + .@"border-block" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-top", .@"border-bottom" } } }, + .@"border-block-color" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-top-color", .@"border-bottom-color" } } }, + .@"border-block-width" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-top-width", .@"border-bottom-width" } } }, + .@"border-block-style" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-top-style", .@"border-bottom-style" } } }, + + .@"border-inline" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-left", .@"border-right" } } }, + .@"border-inline-color" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-left-color", .@"border-right-color" } } }, + .@"border-inline-width" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-left-width", .@"border-right-width" } } }, + .@"border-inline-style" => .{ .block = .{ .logical_borders, &[_]PropertyId{ .@"border-left-style", .@"border-right-style" } } }, + + .@"border-start-start-radius" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{PropertyId{ .@"border-top-left-radius" = VendorPrefix.NONE }}, &[_]PropertyId{PropertyId{ .@"border-top-right-radius" = VendorPrefix.NONE }} } }, + .@"border-start-end-radius" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{PropertyId{ .@"border-top-right-radius" = VendorPrefix.NONE }}, &[_]PropertyId{PropertyId{ .@"border-top-left-radius" = VendorPrefix.NONE }} } }, + .@"border-end-start-radius" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{PropertyId{ .@"border-bottom-left-radius" = VendorPrefix.NONE }}, &[_]PropertyId{PropertyId{ .@"border-bottom-right-radius" = VendorPrefix.NONE }} } }, + .@"border-end-end-radius" => .{ .@"inline" = .{ .logical_borders, &[_]PropertyId{PropertyId{ .@"border-bottom-right-radius" = VendorPrefix.NONE }}, &[_]PropertyId{PropertyId{ .@"border-bottom-left-radius" = VendorPrefix.NONE }} } }, + + else => .none, + }; +} + +fn isTransitionProperty(property_id: *const PropertyId) bool { + return switch (property_id.*) { + .@"transition-property", + .@"transition-duration", + .@"transition-delay", + .@"transition-timing-function", + .transition, + => true, + else => false, + }; +} diff --git a/src/css/properties/ui.zig b/src/css/properties/ui.zig index 58b7cec84d52c4..3740c9418eef30 100644 --- a/src/css/properties/ui.zig +++ b/src/css/properties/ui.zig @@ -41,6 +41,69 @@ pub const ColorScheme = packed struct(u8) { dark: bool = false, /// Forbids the user agent from overriding the color scheme for the element. only: bool = false, + __unused: u5 = 0, + + pub usingnamespace css.Bitflags(@This()); + + const Map = bun.ComptimeEnumMap(enum { normal, only, light, dark }); + + pub fn parse(input: *css.Parser) css.Result(ColorScheme) { + var res = ColorScheme.empty(); + const ident = switch (input.expectIdent()) { + .result => |ident| ident, + .err => |e| return .{ .err = e }, + }; + + if (Map.get(ident)) |value| switch (value) { + .normal => return .{ .result = res }, + .only => res.insert(ColorScheme{ .only = true }), + .light => res.insert(ColorScheme{ .light = true }), + .dark => res.insert(ColorScheme{ .dark = true }), + }; + + while (input.tryParse(css.Parser.expectIdent, .{}).asValue()) |i| { + if (Map.get(i)) |value| switch (value) { + .normal => return .{ .err = input.newCustomError(css.ParserError.invalid_value) }, + .only => { + // Only must be at the start or the end, not in the middle + if (res.contains(ColorScheme{ .only = true })) { + return .{ .err = input.newCustomError(css.ParserError.invalid_value) }; + } + res.insert(ColorScheme{ .only = true }); + return .{ .result = res }; + }, + .light => res.insert(ColorScheme{ .light = true }), + .dark => res.insert(ColorScheme{ .dark = true }), + }; + } + + return .{ .result = res }; + } + + pub fn toCss(this: *const ColorScheme, comptime W: type, dest: *Printer(W)) css.PrintErr!void { + if (this.isEmpty()) { + return dest.writeStr("normal"); + } + + if (this.contains(ColorScheme{ .light = true })) { + try dest.writeStr("light"); + if (this.contains(ColorScheme{ .dark = true })) { + try dest.writeChar(' '); + } + } + + if (this.contains(ColorScheme{ .dark = true })) { + try dest.writeStr("dark"); + } + + if (this.contains(ColorScheme{ .only = true })) { + try dest.writeStr(" only"); + } + } + + pub fn deepClone(this: *const @This(), allocator: Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } }; /// A value for the [resize](https://www.w3.org/TR/2021/WD-css-ui-4-20210316/#resize) property. @@ -107,3 +170,59 @@ pub const Appearance = union(enum) { textarea, non_standard: []const u8, }; + +pub const ColorSchemeHandler = struct { + pub fn handleProperty(_: *@This(), property: *const css.Property, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) bool { + switch (property.*) { + .@"color-scheme" => |*color_scheme_| { + const color_scheme: *const ColorScheme = color_scheme_; + if (!context.targets.isCompatible(css.compat.Feature.light_dark)) { + if (color_scheme.contains(ColorScheme{ .light = true })) { + dest.append( + context.allocator, + defineVar(context.allocator, "--buncss-light", .{ .ident = "initial" }), + ) catch bun.outOfMemory(); + dest.append( + context.allocator, + defineVar(context.allocator, "--buncss-dark", .{ .whitespace = " " }), + ) catch bun.outOfMemory(); + + if (color_scheme.contains(ColorScheme{ .dark = true })) { + context.addDarkRule( + context.allocator, + defineVar(context.allocator, "--buncss-light", .{ .whitespace = " " }), + ); + context.addDarkRule( + context.allocator, + defineVar(context.allocator, "--buncss-dark", .{ .ident = "initial" }), + ); + } + } else if (color_scheme.contains(ColorScheme{ .dark = true })) { + dest.append(context.allocator, defineVar(context.allocator, "--buncss-light", .{ .whitespace = " " })) catch bun.outOfMemory(); + dest.append(context.allocator, defineVar(context.allocator, "--buncss-dark", .{ .ident = "initial" })) catch bun.outOfMemory(); + } + } + dest.append(context.allocator, property.deepClone(context.allocator)) catch bun.outOfMemory(); + return true; + }, + else => return false, + } + } + + pub fn finalize(_: *@This(), _: *css.DeclarationList, _: *css.PropertyHandlerContext) void {} +}; + +fn defineVar(allocator: Allocator, name: []const u8, value: css.Token) css.Property { + return css.Property{ + .custom = css.css_properties.custom.CustomProperty{ + .name = css.css_properties.custom.CustomPropertyName{ .custom = css.DashedIdent{ .v = name } }, + .value = css.TokenList{ + .v = brk: { + var list = ArrayList(css.css_properties.custom.TokenOrValue){}; + list.append(allocator, css.css_properties.custom.TokenOrValue{ .token = value }) catch bun.outOfMemory(); + break :brk list; + }, + }, + }, + }; +} diff --git a/src/css/rules/container.zig b/src/css/rules/container.zig index 13a11ca966d708..13d7203b26e7fe 100644 --- a/src/css/rules/container.zig +++ b/src/css/rules/container.zig @@ -62,7 +62,7 @@ pub const ContainerSizeFeatureId = enum { /// The [orientation](https://w3c.github.io/csswg-drafts/css-contain-3/#orientation) size container feature. orientation, - pub usingnamespace css.DeriveValueType(@This()); + pub usingnamespace css.DeriveValueType(@This(), ValueTypeMap); pub const ValueTypeMap = .{ .width = css.MediaFeatureType.length, @@ -141,7 +141,7 @@ pub const StyleQuery = union(enum) { if (input.expectColon().asErr()) |e| return .{ .err = e }; input.skipWhitespace(); const opts = css.ParserOptions.default(input.allocator(), null); - const feature = .{ + const feature: StyleQuery = .{ .feature = switch (css.Property.parse( property_id, input, diff --git a/src/css/rules/rules.zig b/src/css/rules/rules.zig index 25f7bdec6b3c59..191e55240efb6c 100644 --- a/src/css/rules/rules.zig +++ b/src/css/rules/rules.zig @@ -409,7 +409,9 @@ pub fn CssRuleList(comptime AtRule: type) type { } if (logical.items.len > 0) { - debug("Adding logical: {}\n", .{logical.items[0].style.selectors.debug()}); + if (bun.Environment.isDebug and logical.items[0] == .style) { + debug("Adding logical: {}\n", .{logical.items[0].style.selectors.debug()}); + } var log = CssRuleList(AtRule){ .v = logical }; try log.minify(context, parent_is_unused); rules.appendSlice(context.allocator, log.v.items) catch bun.outOfMemory(); diff --git a/src/css/selectors/parser.zig b/src/css/selectors/parser.zig index 1a7fd7b7bc0010..135b45bc437e75 100644 --- a/src/css/selectors/parser.zig +++ b/src/css/selectors/parser.zig @@ -2153,10 +2153,6 @@ pub fn NthOfSelectorData(comptime Impl: type) type { pub fn nthData(this: *const @This()) NthSelectorData { return this.data; } - - pub fn selectors(this: *const @This()) []GenericSelector(Impl) { - return this.selectors; - } }; } @@ -2250,7 +2246,7 @@ pub const SpecifityAndFlags = struct { flags: SelectorFlags, pub fn eql(this: *const SpecifityAndFlags, other: *const SpecifityAndFlags) bool { - return this.specificity == other.specificity and this.flags.eql(other.flags); + return css.implementEql(@This(), this, other); } pub fn hasPseudoElement(this: *const SpecifityAndFlags) bool { diff --git a/src/css/small_list.zig b/src/css/small_list.zig index cf05e490a3054c..e433f503c2a3cf 100644 --- a/src/css/small_list.zig +++ b/src/css/small_list.zig @@ -404,10 +404,10 @@ pub fn SmallList(comptime T: type, comptime N: comptime_int) type { } pub fn deepClone(this: *const @This(), allocator: Allocator) @This() { - var ret: @This() = .{}; - ret.appendSlice(allocator, this.slice()); - for (ret.slice_mut()) |*item| { - item.* = generic.deepClone(T, item, allocator); + var ret: @This() = initCapacity(allocator, this.len()); + ret.setLen(this.len()); + for (this.slice(), ret.slice_mut()) |*in, *out| { + out.* = generic.deepClone(T, in, allocator); } return ret; } @@ -575,7 +575,7 @@ pub fn SmallList(comptime T: type, comptime N: comptime_int) type { } fn reserveOneUnchecked(this: *@This(), allocator: Allocator) void { - @setCold(true); + @branchHint(.cold); bun.assert(this.len() == this.capacity); const new_cap = growCapacity(this.capacity, this.len() + 1); this.tryGrow(allocator, new_cap); diff --git a/src/css/targets.zig b/src/css/targets.zig index f429e6f2c0fe5d..97c2dda0993423 100644 --- a/src/css/targets.zig +++ b/src/css/targets.zig @@ -31,7 +31,58 @@ pub const Targets = struct { }; } + fn parseDebugTarget(val_: []const u8) ?u32 { + const val = bun.strings.trim(val_, " \n\r\t"); + if (val.len == 0) return null; + if (bun.strings.eqlCaseInsensitiveASCII(val, "null", true)) return null; + + var lhs: u32 = 0; + var rhs: u32 = 0; + + var i: usize = 0; + for (val, 0..) |c, j| { + if (!std.ascii.isDigit(c)) { + i = j; + lhs = std.fmt.parseInt(u32, val[0..j], 10) catch @panic("invalid bytes"); + break; + } + } + if (i >= val.len) { + lhs = std.fmt.parseInt(u32, val, 10) catch @panic("invalid bytes"); + return lhs; + } + if (val[i] != ' ') { + @panic("bad string"); + } + i += 1; + if (val[i] != '<' or i + 1 >= val.len or val[i + 1] != '<') { + @panic("bad string"); + } + i += 2; + if (val[i] != ' ') { + @panic("bad string"); + } + i += 1; + rhs = std.fmt.parseInt(u32, val[i..], 10) catch @panic("invalid bytes"); + return lhs << @intCast(rhs); + } + pub fn forBundlerTarget(target: bun.transpiler.options.Target) Targets { + if (comptime bun.Environment.isDebug) { + var browsers: Browsers = .{}; + const browser_fields = std.meta.fields(Browsers); + var has_any = false; + inline for (browser_fields) |field| { + const env_var = "BUN_DEBUG_CSS_TARGET_" ++ field.name; + if (bun.getenvZAnyCase(env_var)) |val| { + @field(browsers, field.name) = parseDebugTarget(val); + has_any = true; + } + } + if (has_any) { + return .{ .browsers = browsers }; + } + } return switch (target) { .node, .bun => runtimeDefault(), .browser, .bun_macro, .bake_server_components_ssr => browserDefault(), @@ -135,7 +186,6 @@ pub const Features = packed struct(u32) { vendor_prefixes: bool = false, logical_properties: bool = false, __unused: u12 = 0, - pub const selectors = Features.fromNames(&.{ "nesting", "not_selector_list", "dir_selector", "lang_selector_list", "is_selector" }); pub const media_queries = Features.fromNames(&.{ "media_interval_syntax", "media_range_syntax", "custom_media_queries" }); pub const colors = Features.fromNames(&.{ "color_function", "oklab_colors", "lab_colors", "p3_colors", "hex_alpha_colors", "space_separated_color_notation" }); diff --git a/src/css/values/angle.zig b/src/css/values/angle.zig index ee207c553a8053..46499607158785 100644 --- a/src/css/values/angle.zig +++ b/src/css/values/angle.zig @@ -183,6 +183,10 @@ pub const Angle = union(Tag) { return map(this, opfn); } + pub fn addInternal(this: Angle, _: std.mem.Allocator, other: Angle) Angle { + return this.add(other); + } + pub fn add(this: Angle, rhs: Angle) Angle { const addfn = struct { pub fn add(_: void, a: f32, b: f32) f32 { @@ -240,19 +244,19 @@ pub const Angle = union(Tag) { comptime op_fn: *const fn (@TypeOf(ctx), a: f32, b: f32) f32, ) Angle { // PERF: not sure if this is faster - const self_tag: u8 = @intFromEnum(this.*); - const other_tag: u8 = @intFromEnum(this.*); - const DEG: u8 = @intFromEnum(Tag.deg); - const GRAD: u8 = @intFromEnum(Tag.grad); - const RAD: u8 = @intFromEnum(Tag.rad); - const TURN: u8 = @intFromEnum(Tag.turn); - - const switch_val: u8 = self_tag | other_tag; + const self_tag: u16 = @intFromEnum(this.*); + const other_tag: u16 = @intFromEnum(other.*); + const DEG: u16 = @intFromEnum(Tag.deg); + const GRAD: u16 = @intFromEnum(Tag.grad); + const RAD: u16 = @intFromEnum(Tag.rad); + const TURN: u16 = @intFromEnum(Tag.turn); + + const switch_val: u16 = self_tag | (other_tag << 8); return switch (switch_val) { - DEG | DEG => Angle{ .deg = op_fn(ctx, this.deg, other.deg) }, - RAD | RAD => Angle{ .rad = op_fn(ctx, this.rad, other.rad) }, - GRAD | GRAD => Angle{ .grad = op_fn(ctx, this.grad, other.grad) }, - TURN | TURN => Angle{ .turn = op_fn(ctx, this.turn, other.turn) }, + DEG | (DEG << 8) => Angle{ .deg = op_fn(ctx, this.deg, other.deg) }, + RAD | (RAD << 8) => Angle{ .rad = op_fn(ctx, this.rad, other.rad) }, + GRAD | (GRAD << 8) => Angle{ .grad = op_fn(ctx, this.grad, other.grad) }, + TURN | (TURN << 8) => Angle{ .turn = op_fn(ctx, this.turn, other.turn) }, else => Angle{ .deg = op_fn(ctx, this.toDegrees(), other.toDegrees()) }, }; } diff --git a/src/css/values/calc.zig b/src/css/values/calc.zig index cf4d2137380257..a86ee0d9fcbb60 100644 --- a/src/css/values/calc.zig +++ b/src/css/values/calc.zig @@ -169,20 +169,15 @@ pub fn Calc(comptime V: type) type { } // TODO: addValueOwned - fn addValue(allocator: Allocator, lhs: V, rhs: V) V { + pub fn addValue(allocator: Allocator, lhs: V, rhs: V) V { return switch (V) { f32 => return lhs + rhs, - Angle => return lhs.add(rhs), - // CSSNumber => return lhs.add(rhs), - Length => return lhs.add(allocator, rhs), - Percentage => return lhs.add(allocator, rhs), - Time => return lhs.add(allocator, rhs), - else => lhs.add(allocator, rhs), + else => lhs.addInternal(allocator, rhs), }; } // TODO: intoValueOwned - fn intoValue(this: @This(), allocator: std.mem.Allocator) V { + pub fn intoValue(this: @This(), allocator: std.mem.Allocator) V { switch (V) { Angle => return switch (this) { .value => |v| v.*, @@ -222,19 +217,26 @@ pub fn Calc(comptime V: type) type { } } + pub fn intoCalc(val: V, allocator: std.mem.Allocator) Calc(V) { + return switch (V) { + f32 => .{ .value = bun.create(allocator, f32, val) }, + else => val.intoCalc(allocator), + }; + } + // TODO: change to addOwned() pub fn add(this: @This(), allocator: std.mem.Allocator, rhs: @This()) @This() { if (this == .value and rhs == .value) { // PERF: we can reuse the allocation here - return .{ .value = bun.create(allocator, V, addValue(allocator, this.value.*, rhs.value.*)) }; + return intoCalc(addValue(allocator, this.value.*, rhs.value.*), allocator); } else if (this == .number and rhs == .number) { return .{ .number = this.number + rhs.number }; } else if (this == .value) { // PERF: we can reuse the allocation here - return .{ .value = bun.create(allocator, V, addValue(allocator, this.value.*, intoValue(rhs, allocator))) }; + return intoCalc(addValue(allocator, this.value.*, intoValue(rhs, allocator)), allocator); } else if (rhs == .value) { // PERF: we can reuse the allocation here - return .{ .value = bun.create(allocator, V, addValue(allocator, intoValue(this, allocator), rhs.value.*)) }; + return intoCalc(addValue(allocator, intoValue(this, allocator), rhs.value.*), allocator); } else if (this == .function) { return This{ .sum = .{ @@ -250,11 +252,7 @@ pub fn Calc(comptime V: type) type { }, }; } else { - return .{ .value = bun.create( - allocator, - V, - addValue(allocator, intoValue(this, allocator), intoValue(rhs, allocator)), - ) }; + return intoCalc(addValue(allocator, intoValue(this, allocator), intoValue(rhs, allocator)), allocator); } } diff --git a/src/css/values/color.zig b/src/css/values/color.zig index e742af54b745c7..31331bd72aed4d 100644 --- a/src/css/values/color.zig +++ b/src/css/values/color.zig @@ -230,16 +230,14 @@ pub const CssColor = union(enum) { }, .light_dark => |*light_dark| { if (!dest.targets.isCompatible(css.compat.Feature.light_dark)) { - // TODO(zack): lightningcss -> buncss - try dest.writeStr("var(--lightningcss-light"); + try dest.writeStr("var(--buncss-light"); try dest.delim(',', false); try light_dark.light.toCss(W, dest); try dest.writeChar(')'); try dest.whitespace(); - try dest.writeStr("var(--lightningcss-dark"); + try dest.writeStr("var(--buncss-dark"); try dest.delim(',', false); try light_dark.dark.toCss(W, dest); - try light_dark.dark.toCss(W, dest); return dest.writeChar(')'); } @@ -262,7 +260,7 @@ pub const CssColor = union(enum) { }; switch (token.*) { - .hash, .idhash => |v| { + .unrestrictedhash, .idhash => |v| { const r, const g, const b, const a = css.color.parseHashColor(v) orelse return .{ .err = location.newUnexpectedTokenError(token.*) }; return .{ .result = .{ .rgba = RGBA.new(r, g, b, a), @@ -365,7 +363,7 @@ pub const CssColor = union(enum) { if (this.* == .light_dark or other.* == .light_dark) { const this_light_dark = this.toLightDark(allocator); - const other_light_dark = this.toLightDark(allocator); + const other_light_dark = other.toLightDark(allocator); const al = this_light_dark.light_dark.light; const ad = this_light_dark.light_dark.dark; @@ -508,7 +506,8 @@ pub const CssColor = union(enum) { } if (fallbacks.contains(ColorFallbackKind{ .lab = true })) { - this.* = this.toLAB(allocator).?; + const foo = this.toLAB(allocator).?; + this.* = foo; } return res; @@ -532,7 +531,7 @@ pub const CssColor = union(enum) { if (lab.* == .lab or lab.* == .lch and targets.shouldCompileSame(.lab_colors)) break :brk ColorFallbackKind.andBelow(.{ .lab = true }); if (lab.* == .oklab or lab.* == .oklch and targets.shouldCompileSame(.oklab_colors)) - break :brk ColorFallbackKind.andBelow(.{ .lab = true }); + break :brk ColorFallbackKind.andBelow(.{ .oklab = true }); return ColorFallbackKind.empty(); }, .predefined => |predefined| brk: { @@ -1621,7 +1620,7 @@ pub const LAB = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace UnboundedColorGamut(@This()); @@ -1651,7 +1650,7 @@ pub const SRGB = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace BoundedColorGamut(@This()); @@ -1691,7 +1690,7 @@ pub const HSL = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace HslHwbColorGamut(@This(), "s", "l"); @@ -1735,7 +1734,7 @@ pub const HWB = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace HslHwbColorGamut(@This(), "w", "b"); @@ -1774,7 +1773,7 @@ pub const SRGBLinear = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace BoundedColorGamut(@This()); @@ -1804,7 +1803,7 @@ pub const P3 = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace BoundedColorGamut(@This()); @@ -1828,7 +1827,7 @@ pub const A98 = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace BoundedColorGamut(@This()); @@ -1852,7 +1851,7 @@ pub const ProPhoto = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace BoundedColorGamut(@This()); @@ -1876,7 +1875,7 @@ pub const Rec2020 = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace BoundedColorGamut(@This()); @@ -1900,7 +1899,7 @@ pub const XYZd50 = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace UnboundedColorGamut(@This()); @@ -1927,7 +1926,7 @@ pub const XYZd65 = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace UnboundedColorGamut(@This()); @@ -1957,7 +1956,7 @@ pub const LCH = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace UnboundedColorGamut(@This()); @@ -1985,7 +1984,7 @@ pub const OKLAB = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace UnboundedColorGamut(@This()); @@ -2015,7 +2014,7 @@ pub const OKLCH = struct { /// The alpha component. alpha: f32, - pub usingnamespace DefineColorspace(@This()); + pub usingnamespace DefineColorspace(@This(), ChannelTypeMap); pub usingnamespace ColorspaceConversions(@This()); pub usingnamespace UnboundedColorGamut(@This()); @@ -2791,6 +2790,7 @@ pub fn parseColorMix(input: *css.Parser) Result(CssColor) { } else .{ .result = HueInterpolationMethod.shorter }; const hue_method = hue_method_.unwrapOr(HueInterpolationMethod.shorter); + if (input.expectComma().asErr()) |e| return .{ .err = e }; const first_percent_ = input.tryParse(css.Parser.expectPercentage, .{}); const first_color = switch (CssColor.parse(input)) { @@ -2820,9 +2820,9 @@ pub fn parseColorMix(input: *css.Parser) Result(CssColor) { }; // https://drafts.csswg.org/css-color-5/#color-mix-percent-norm - const p1, const p2 = if (first_percent == null and second_percent == null) .{ 0.5, 0.5 } else brk: { - const p2 = second_percent orelse (1.0 - first_percent.?); - const p1 = first_percent orelse (1.0 - second_percent.?); + const p1: f32, const p2: f32 = if (first_percent == null and second_percent == null) .{ @as(f32, 0.5), @as(f32, 0.5) } else brk: { + const p2 = second_percent orelse (@as(f32, 1.0) - first_percent.?); + const p1 = first_percent orelse (@as(f32, 1.0) - second_percent.?); break :brk .{ p1, p2 }; }; @@ -3037,12 +3037,7 @@ pub fn ColorspaceConversions(comptime T: type) type { }; } -pub fn DefineColorspace(comptime T: type) type { - if (!@hasDecl(T, "ChannelTypeMap")) { - @compileError("A Colorspace must define a ChannelTypeMap"); - } - const ChannelTypeMap = T.ChannelTypeMap; - +pub fn DefineColorspace(comptime T: type, comptime ChannelTypeMap: anytype) type { const fields: []const std.builtin.Type.StructField = std.meta.fields(T); const a = fields[0].name; const b = fields[1].name; @@ -4016,7 +4011,7 @@ const color_conversions = struct { const xyz = _xyz.resolveMissing(); const x = xyz.x / D50[0]; const y = xyz.y / D50[1]; - const z = xyz.y / D50[2]; + const z = xyz.z / D50[2]; // now compute f @@ -4028,7 +4023,7 @@ const color_conversions = struct { const l = ((116.0 * f1) - 16.0) / 100.0; const a = 500.0 * (f0 - f1); - const b = 500.0 * (f1 - f2); + const b = 200.0 * (f1 - f2); return LAB{ .l = l, diff --git a/src/css/values/color_js.zig b/src/css/values/color_js.zig index d1dd0f6abc80bb..ca07f17bc27cbf 100644 --- a/src/css/values/color_js.zig +++ b/src/css/values/color_js.zig @@ -232,7 +232,7 @@ pub fn jsFunctionColor(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFram }; } - input = args[0].toSlice(globalThis, bun.default_allocator); + input = try args[0].toSlice(globalThis, bun.default_allocator); var parser_input = css.ParserInput.new(allocator, input.slice()); var parser = css.Parser.new(&parser_input, null); @@ -420,6 +420,7 @@ pub fn jsFunctionColor(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFram // Fallback to CSS string output var dest = std.ArrayListUnmanaged(u8){}; + defer dest.deinit(allocator); const writer = dest.writer(allocator); var printer = css.Printer(@TypeOf(writer)).new( @@ -434,8 +435,7 @@ pub fn jsFunctionColor(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFram return globalThis.throw("color() internal error: {s}", .{@errorName(err)}); }; - var out = bun.String.createUTF8(dest.items); - return out.transferToJS(globalThis); + return bun.String.createUTF8ForJS(globalThis, dest.items); }, } } diff --git a/src/css/values/easing.zig b/src/css/values/easing.zig index b5e5ea51c2a3e7..6de9a827b4143e 100644 --- a/src/css/values/easing.zig +++ b/src/css/values/easing.zig @@ -46,15 +46,45 @@ pub const EasingFunction = union(enum) { x2: CSSNumber, /// The y-position of the second point in the curve. y2: CSSNumber, + + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } + + pub fn __generateDeepClone() void {} }, /// A step easing function. steps: struct { /// The number of intervals in the function. count: CSSInteger, /// The step position. - position: StepPosition = StepPosition.default, + position: StepPosition = StepPosition.default(), + + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } + + pub fn __generateDeepClone() void {} }, + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { + return css.implementEql(@This(), lhs, rhs); + } + + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } + + const Map = bun.ComptimeEnumMap(enum { + linear, + ease, + @"ease-in", + @"ease-out", + @"ease-in-out", + @"step-start", + @"step-end", + }); + pub fn parse(input: *css.Parser) Result(EasingFunction) { const location = input.currentSourceLocation(); if (input.tryParse(struct { @@ -62,23 +92,16 @@ pub const EasingFunction = union(enum) { return i.expectIdent(); } }.parse, .{}).asValue()) |ident| { - // todo_stuff.match_ignore_ascii_case - const keyword = if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "linear")) - EasingFunction.linear - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "ease")) - EasingFunction.ease - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "ease-in")) - EasingFunction.ease_in - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "ease-out")) - EasingFunction.ease_out - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "ease-in-out")) - EasingFunction.ease_in_out - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "step-start")) - EasingFunction{ .steps = .{ .count = 1, .position = .start } } - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "step-end")) - EasingFunction{ .steps = .{ .count = 1, .position = .end } } - else - return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) }; + const keyword = if (Map.getASCIIICaseInsensitive(ident)) |e| switch (e) { + .linear => EasingFunction.linear, + .ease => EasingFunction.ease, + .@"ease-in" => EasingFunction.ease_in, + .@"ease-out" => EasingFunction.ease_out, + .@"ease-in-out" => EasingFunction.ease_in_out, + .@"step-start" => EasingFunction{ .steps = .{ .count = 1, .position = .start } }, + .@"step-end" => EasingFunction{ .steps = .{ .count = 1, .position = .end } }, + } else return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) }; + return .{ .result = keyword }; } @@ -86,12 +109,13 @@ pub const EasingFunction = union(enum) { .result => |vv| vv, .err => |e| return .{ .err = e }, }; + const Closure = struct { loc: css.SourceLocation, function: []const u8 }; return input.parseNestedBlock( EasingFunction, - .{ .loc = location, .function = function }, + &Closure{ .loc = location, .function = function }, struct { fn parse( - closure: *const struct { loc: css.SourceLocation, function: []const u8 }, + closure: *const Closure, i: *css.Parser, ) Result(EasingFunction) { if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(closure.function, "cubic-bezier")) { @@ -125,10 +149,10 @@ pub const EasingFunction = union(enum) { if (p.expectComma().asErr()) |e| return .{ .err = e }; return StepPosition.parse(p); } - }.parse, .{}).unwrapOr(StepPosition.default); + }.parse, .{}).unwrapOr(StepPosition.default()); return .{ .result = EasingFunction{ .steps = .{ .count = count, .position = position } } }; } else { - return closure.loc.newUnexpectedTokenError(.{ .ident = closure.function }); + return .{ .err = closure.loc.newUnexpectedTokenError(.{ .ident = closure.function }) }; } } }.parse, @@ -145,21 +169,21 @@ pub const EasingFunction = union(enum) { else => { if (this.isEase()) { return dest.writeStr("ease"); - } else if (this == .cubic_bezier and std.meta.eql(this.cubic_bezier, .{ + } else if (this.* == .cubic_bezier and this.cubic_bezier.eql(&.{ .x1 = 0.42, .y1 = 0.0, .x2 = 1.0, .y2 = 1.0, })) { return dest.writeStr("ease-in"); - } else if (this == .cubic_bezier and std.meta.eql(this.cubic_bezier, .{ + } else if (this.* == .cubic_bezier and this.cubic_bezier.eql(&.{ .x1 = 0.0, .y1 = 0.0, .x2 = 0.58, .y2 = 1.0, })) { return dest.writeStr("ease-out"); - } else if (this == .cubic_bezier and std.meta.eql(this.cubic_bezier, .{ + } else if (this.* == .cubic_bezier and this.cubic_bezier.eql(&.{ .x1 = 0.42, .y1 = 0.0, .x2 = 0.58, @@ -171,13 +195,13 @@ pub const EasingFunction = union(enum) { switch (this.*) { .cubic_bezier => |cb| { try dest.writeStr("cubic-bezier("); - try css.generic.toCss(cb.x1, W, dest); + try css.generic.toCss(CSSNumber, &cb.x1, W, dest); try dest.writeChar(','); - try css.generic.toCss(cb.y1, W, dest); + try css.generic.toCss(CSSNumber, &cb.y1, W, dest); try dest.writeChar(','); - try css.generic.toCss(cb.x2, W, dest); + try css.generic.toCss(CSSNumber, &cb.x2, W, dest); try dest.writeChar(','); - try css.generic.toCss(cb.y2, W, dest); + try css.generic.toCss(CSSNumber, &cb.y2, W, dest); try dest.writeChar(')'); }, .steps => { @@ -187,7 +211,6 @@ pub const EasingFunction = union(enum) { if (this.steps.count == 1 and this.steps.position == .end) { return try dest.writeStr("step-end"); } - try dest.writeStr("steps("); try dest.writeFmt("steps({d}", .{this.steps.count}); try dest.delim(',', false); try this.steps.position.toCss(W, dest); @@ -199,10 +222,15 @@ pub const EasingFunction = union(enum) { }; } + /// Returns whether the given string is a valid easing function name. + pub fn isIdent(s: []const u8) bool { + return Map.getASCIIICaseInsensitive(s) != null; + } + /// Returns whether the easing function is equivalent to the `ease` keyword. pub fn isEase(this: *const EasingFunction) bool { return this.* == .ease or - (this.* == .cubic_bezier and std.meta.eql(this.cubic_bezier == .{ + (this.* == .cubic_bezier and this.cubic_bezier.eql(&.{ .x1 = 0.25, .y1 = 0.1, .x2 = 0.25, @@ -218,18 +246,20 @@ pub const StepPosition = enum { /// The last rise occurs at input progress value of 1. end, /// All rises occur within the range (0, 1). - jump_none, + @"jump-none", /// The first rise occurs at input progress value of 0 and the last rise occurs at input progress value of 1. - jump_both, + @"jump-both", - // TODO: implement this - // pub usingnamespace css.DeriveToCss(@This()); + pub usingnamespace css.DeriveToCss(@This()); - pub fn toCss(this: *const StepPosition, comptime W: type, dest: *css.Printer(W)) css.PrintErr!void { - _ = this; // autofix - _ = dest; // autofix - @compileError(css.todo_stuff.depth); - } + const Map = bun.ComptimeEnumMap(enum { + start, + end, + @"jump-none", + @"jump-both", + @"jump-start", + @"jump-end", + }); pub fn parse(input: *css.Parser) Result(StepPosition) { const location = input.currentSourceLocation(); @@ -237,21 +267,19 @@ pub const StepPosition = enum { .result => |vv| vv, .err => |e| return .{ .err = e }, }; - // todo_stuff.match_ignore_ascii_case - const keyword = if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "start")) - StepPosition.start - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "end")) - StepPosition.end - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "jump-start")) - StepPosition.start - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "jump-end")) - StepPosition.end - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "jump-none")) - StepPosition.jump_none - else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength(ident, "jump-both")) - StepPosition.jump_both - else - return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) }; + const keyword = if (Map.getASCIIICaseInsensitive(ident)) |e| switch (e) { + .start => StepPosition.start, + .end => StepPosition.end, + .@"jump-start" => StepPosition.start, + .@"jump-end" => StepPosition.end, + .@"jump-none" => StepPosition.@"jump-none", + .@"jump-both" => StepPosition.@"jump-both", + } else return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) }; + return .{ .result = keyword }; } + + pub fn default() StepPosition { + return .end; + } }; diff --git a/src/css/values/gradient.zig b/src/css/values/gradient.zig index 0910a65a780c19..0ee9d2010d15cc 100644 --- a/src/css/values/gradient.zig +++ b/src/css/values/gradient.zig @@ -450,7 +450,7 @@ pub const LinearGradient = struct { } pub fn eql(this: *const LinearGradient, other: *const LinearGradient) bool { - return this.vendor_prefix.eql(other.vendor_prefix) and this.direction.eql(&other.direction) and css.generic.eqlList(GradientItem(LengthPercentage), &this.items, &other.items); + return css.implementEql(@This(), this, other); } pub fn getFallback(this: *const @This(), allocator: std.mem.Allocator, kind: css.ColorFallbackKind) LinearGradient { @@ -561,10 +561,7 @@ pub const RadialGradient = struct { } pub fn eql(this: *const RadialGradient, other: *const RadialGradient) bool { - return this.vendor_prefix.eql(other.vendor_prefix) and - this.shape.eql(&other.shape) and - this.position.eql(&other.position) and - css.generic.eqlList(GradientItem(LengthPercentage), &this.items, &other.items); + return css.implementEql(@This(), this, other); } }; @@ -656,9 +653,7 @@ pub const ConicGradient = struct { } pub fn eql(this: *const ConicGradient, other: *const ConicGradient) bool { - return this.angle.eql(&other.angle) and - this.position.eql(&other.position) and - css.generic.eqlList(GradientItem(AnglePercentage), &this.items, &other.items); + return css.implementEql(@This(), this, other); } }; @@ -676,6 +671,10 @@ pub const WebKitGradient = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A radial `-webkit-gradient()`. radial: struct { @@ -693,6 +692,10 @@ pub const WebKitGradient = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, pub fn parse(input: *css.Parser) Result(WebKitGradient) { @@ -917,16 +920,7 @@ pub const WebKitGradient = union(enum) { } pub fn eql(this: *const WebKitGradient, other: *const WebKitGradient) bool { - return switch (this.*) { - .linear => |*a| switch (other.*) { - .linear => a.from.eql(&other.linear.from) and a.to.eql(&other.linear.to) and css.generic.eqlList(WebKitColorStop, &a.stops, &other.linear.stops), - else => false, - }, - .radial => |*a| switch (other.*) { - .radial => a.from.eql(&other.radial.from) and a.to.eql(&other.radial.to) and a.r0 == other.radial.r0 and a.r1 == other.radial.r1 and css.generic.eqlList(WebKitColorStop, &a.stops, &other.radial.stops), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } }; @@ -950,6 +944,10 @@ pub const LineDirection = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { @@ -957,24 +955,7 @@ pub const LineDirection = union(enum) { } pub fn eql(this: *const LineDirection, other: *const LineDirection) bool { - return switch (this.*) { - .angle => |*a| switch (other.*) { - .angle => a.eql(&other.angle), - else => false, - }, - .horizontal => |*v| switch (other.*) { - .horizontal => v.* == other.horizontal, - else => false, - }, - .vertical => |*v| switch (other.*) { - .vertical => v.* == other.vertical, - else => false, - }, - .corner => |*c| switch (other.*) { - .corner => c.horizontal == other.corner.horizontal and c.vertical == other.corner.vertical, - else => false, - }, - }; + return css.implementEql(@This(), this, other); } pub fn parse(input: *css.Parser, is_prefixed: bool) Result(LineDirection) { @@ -1071,16 +1052,7 @@ pub fn GradientItem(comptime D: type) type { } pub fn eql(this: *const GradientItem(D), other: *const GradientItem(D)) bool { - return switch (this.*) { - .color_stop => |*a| switch (other.*) { - .color_stop => a.eql(&other.color_stop), - else => false, - }, - .hint => |*a| switch (other.*) { - .hint => css.generic.eql(D, a, &other.hint), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { @@ -1138,16 +1110,7 @@ pub const EndingShape = union(enum) { } pub fn eql(this: *const EndingShape, other: *const EndingShape) bool { - return switch (this.*) { - .ellipse => |*a| switch (other.*) { - .ellipse => a.eql(&other.ellipse), - else => false, - }, - .circle => |*a| switch (other.*) { - .circle => a.eql(&other.circle), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } }; @@ -1177,7 +1140,7 @@ pub const WebKitGradientPoint = struct { } pub fn eql(this: *const WebKitGradientPoint, other: *const WebKitGradientPoint) bool { - return this.x.eql(&other.x) and this.y.eql(&other.y); + return css.implementEql(@This(), this, other); } pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { @@ -1262,20 +1225,7 @@ pub fn WebKitGradientPointComponent(comptime S: type) type { } pub fn eql(this: *const This, other: *const This) bool { - return switch (this.*) { - .center => switch (other.*) { - .center => true, - else => false, - }, - .number => |*a| switch (other.*) { - .number => a.eql(&other.number), - else => false, - }, - .side => |*a| switch (other.*) { - .side => |*b| a.eql(&b.*), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } }; } @@ -1398,7 +1348,7 @@ pub fn ColorStop(comptime D: type) type { } pub fn eql(this: *const This, other: *const This) bool { - return this.color.eql(&other.color) and css.generic.eql(?D, &this.position, &other.position); + return css.implementEql(@This(), this, other); } }; } @@ -1417,6 +1367,10 @@ pub const Ellipse = union(enum) { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, /// A shape extent keyword. extent: ShapeExtent, @@ -1479,7 +1433,7 @@ pub const Ellipse = union(enum) { } pub fn eql(this: *const Ellipse, other: *const Ellipse) bool { - return this.size.x.eql(&other.size.x) and this.size.y.eql(&other.size.y) and this.extent.eql(&other.extent); + return css.implementEql(@This(), this, other); } }; @@ -1571,7 +1525,7 @@ pub const Circle = union(enum) { } pub fn eql(this: *const Circle, other: *const Circle) bool { - return this.radius.eql(&other.radius) and this.extent.eql(&other.extent); + return css.implementEql(@This(), this, other); } }; diff --git a/src/css/values/image.zig b/src/css/values/image.zig index fc82ef938fb2bf..2ed2c1df71d1ee 100644 --- a/src/css/values/image.zig +++ b/src/css/values/image.zig @@ -95,24 +95,7 @@ pub const Image = union(enum) { } pub inline fn eql(this: *const Image, other: *const Image) bool { - return switch (this.*) { - .none => switch (other.*) { - .none => true, - else => false, - }, - .url => |*a| switch (other.*) { - .url => a.eql(&other.url), - else => false, - }, - .image_set => |*a| switch (other.*) { - .image_set => a.eql(&other.image_set), - else => false, - }, - .gradient => |a| switch (other.*) { - .gradient => a.eql(other.gradient), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { @@ -294,7 +277,7 @@ pub const ImageSet = struct { } pub fn eql(this: *const ImageSet, other: *const ImageSet) bool { - return this.vendor_prefix.eql(other.vendor_prefix) and css.generic.eqlList(ImageSetOption, &this.options, &other.options); + return css.implementEql(@This(), this, other); } pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { @@ -411,12 +394,7 @@ pub const ImageSetOption = struct { } pub fn eql(lhs: *const ImageSetOption, rhs: *const ImageSetOption) bool { - return lhs.image.eql(&rhs.image) and lhs.resolution.eql(&rhs.resolution) and (brk: { - if (lhs.file_type != null and rhs.file_type != null) { - break :brk bun.strings.eql(lhs.file_type.?, rhs.file_type.?); - } - break :brk false; - }); + return css.implementEql(@This(), lhs, rhs); } }; diff --git a/src/css/values/length.zig b/src/css/values/length.zig index b3a9fe12e4d488..2983788a971602 100644 --- a/src/css/values/length.zig +++ b/src/css/values/length.zig @@ -34,10 +34,7 @@ pub const LengthOrNumber = union(enum) { } pub fn eql(this: *const @This(), other: *const @This()) bool { - return switch (this.*) { - .number => |*n| n.* == other.number, - .length => |*l| l.eql(&other.length), - }; + return css.implementEql(@This(), this, other); } pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { @@ -311,6 +308,10 @@ pub const LengthValue = union(enum) { unreachable; } + pub fn deepClone(this: *const @This(), _: std.mem.Allocator) @This() { + return this.*; + } + pub fn zero() LengthValue { return .{ .px = 0.0 }; } @@ -354,7 +355,7 @@ pub const LengthValue = union(enum) { } pub fn sign(this: *const @This()) f32 { - const enum_fields = @typeInfo(@typeInfo(@This()).Union.tag_type.?).Enum.fields; + const enum_fields = @typeInfo(@typeInfo(@This()).@"union".tag_type.?).@"enum".fields; inline for (std.meta.fields(@This()), 0..) |field, i| { if (enum_fields[i].value == @intFromEnum(this.*)) { return css.signfns.signF32(@field(this, field.name)); @@ -378,7 +379,7 @@ pub const LengthValue = union(enum) { } pub fn toUnitValue(this: *const @This()) struct { CSSNumber, []const u8 } { - const enum_fields = @typeInfo(@typeInfo(@This()).Union.tag_type.?).Enum.fields; + const enum_fields = @typeInfo(@typeInfo(@This()).@"union".tag_type.?).@"enum".fields; inline for (std.meta.fields(@This()), 0..) |field, i| { if (enum_fields[i].value == @intFromEnum(this.*)) { return .{ @field(this, field.name), field.name }; @@ -523,6 +524,10 @@ pub const Length = union(enum) { /// A computed length value using `calc()`. calc: *Calc(Length), + pub fn zero() Length { + return .{ .value = LengthValue.zero() }; + } + pub fn deepClone(this: *const Length, allocator: Allocator) Length { return switch (this.*) { .value => |v| .{ .value = v }, @@ -569,10 +574,7 @@ pub const Length = union(enum) { } pub fn eql(this: *const @This(), other: *const @This()) bool { - return switch (this.*) { - .value => |a| other.* == .value and a.eql(&other.value), - .calc => |a| other.* == .calc and a.eql(other.calc), - }; + return css.implementEql(@This(), this, other); } pub fn px(p: CSSNumber) Length { @@ -615,12 +617,12 @@ pub const Length = union(enum) { return res; } - fn addInternal(this: Length, allocator: Allocator, other: Length) Length { + pub fn addInternal(this: Length, allocator: Allocator, other: Length) Length { if (this.tryAdd(allocator, &other)) |r| return r; return this.add__(allocator, other); } - fn intoCalc(this: Length, allocator: Allocator) Calc(Length) { + pub fn intoCalc(this: Length, allocator: Allocator) Calc(Length) { return switch (this) { .calc => |c| c.*, else => |v| Calc(Length){ .value = bun.create(allocator, Length, v) }, diff --git a/src/css/values/number.zig b/src/css/values/number.zig index ddb701a7c0cc31..448ccb71ada054 100644 --- a/src/css/values/number.zig +++ b/src/css/values/number.zig @@ -25,19 +25,13 @@ pub const CSSNumberFns = struct { pub fn toCss(this: *const CSSNumber, comptime W: type, dest: *Printer(W)) PrintErr!void { const number: f32 = this.*; if (number != 0.0 and @abs(number) < 1.0) { - // PERF(alloc): Use stack fallback here? - // why the extra allocation anyway? isn't max amount of digits to stringify an f32 small? - var s = ArrayList(u8){}; - defer s.deinit(dest.allocator); - const writer = s.writer(dest.allocator); - css.to_css.float32(number, writer) catch { - return dest.addFmtError(); - }; + var dtoa_buf: [129]u8 = undefined; + const str, _ = try css.dtoa_short(&dtoa_buf, number, 6); if (number < 0.0) { try dest.writeChar('-'); - try dest.writeStr(bun.strings.trimLeadingPattern2(s.items, '-', '0')); + try dest.writeStr(bun.strings.trimLeadingPattern2(str, '-', '0')); } else { - try dest.writeStr(bun.strings.trimLeadingChar(s.items, '0')); + try dest.writeStr(bun.strings.trimLeadingChar(str, '0')); } } else { return css.to_css.float32(number, dest) catch { diff --git a/src/css/values/percentage.zig b/src/css/values/percentage.zig index 081206f7d0bf01..d0795ec4268068 100644 --- a/src/css/values/percentage.zig +++ b/src/css/values/percentage.zig @@ -62,10 +62,18 @@ pub const Percentage = struct { return this.v == other.v; } + pub fn addInternal(this: Percentage, allocator: std.mem.Allocator, other: Percentage) Percentage { + return this.add(allocator, other); + } + pub fn add(lhs: Percentage, _: std.mem.Allocator, rhs: Percentage) Percentage { return Percentage{ .v = lhs.v + rhs.v }; } + pub fn intoCalc(this: Percentage, allocator: std.mem.Allocator) Calc(Percentage) { + return Calc(Percentage){ .value = bun.create(allocator, Percentage, this) }; + } + pub fn mulF32(this: Percentage, _: std.mem.Allocator, other: f32) Percentage { return Percentage{ .v = this.v * other }; } @@ -267,7 +275,7 @@ pub fn DimensionPercentage(comptime D: type) type { }; } - fn addInternal(this: This, allocator: std.mem.Allocator, other: This) This { + pub fn addInternal(this: This, allocator: std.mem.Allocator, other: This) This { if (this.addRecursive(allocator, &other)) |res| return res; return this.addImpl(allocator, other); } @@ -285,12 +293,12 @@ pub fn DimensionPercentage(comptime D: type) type { .sum => |sum| { const left_calc = This{ .calc = sum.left }; if (left_calc.addRecursive(allocator, other)) |res| { - return res.add(allocator, This{ .calc = sum.right }); + return res.addImpl(allocator, This{ .calc = sum.right }); } const right_calc = This{ .calc = sum.right }; if (right_calc.addRecursive(allocator, other)) |res| { - return (This{ .calc = sum.left }).add(allocator, res); + return (This{ .calc = sum.left }).addImpl(allocator, res); } }, else => {}, @@ -301,12 +309,12 @@ pub fn DimensionPercentage(comptime D: type) type { .sum => |sum| { const left_calc = This{ .calc = sum.left }; if (this.addRecursive(allocator, &left_calc)) |res| { - return res.add(allocator, This{ .calc = sum.right }); + return res.addImpl(allocator, This{ .calc = sum.right }); } const right_calc = This{ .calc = sum.right }; if (this.addRecursive(allocator, &right_calc)) |res| { - return (This{ .calc = sum.left }).add(allocator, res); + return (This{ .calc = sum.left }).addImpl(allocator, res); } }, else => {}, @@ -331,7 +339,7 @@ pub fn DimensionPercentage(comptime D: type) type { return .{ .calc = bun.create(allocator, Calc(DimensionPercentage(D)), a.calc.add(allocator, b.calc.*)) }; } else if (a == .calc) { if (a.calc.* == .value) { - return a.calc.value.add(allocator, b); + return a.calc.value.addImpl(allocator, b); } else { return .{ .calc = bun.create( @@ -346,7 +354,7 @@ pub fn DimensionPercentage(comptime D: type) type { } } else if (b == .calc) { if (b.calc.* == .value) { - return a.add(allocator, b.calc.value.*); + return a.addImpl(allocator, b.calc.value.*); } else { return .{ .calc = bun.create( @@ -484,16 +492,7 @@ pub const NumberOrPercentage = union(enum) { } pub fn eql(this: *const NumberOrPercentage, other: *const NumberOrPercentage) bool { - return switch (this.*) { - .number => |*a| switch (other.*) { - .number => a.* == other.number, - .percentage => false, - }, - .percentage => |*a| switch (other.*) { - .number => false, - .percentage => a.eql(&other.percentage), - }, - }; + return css.implementEql(@This(), this, other); } pub fn intoF32(this: *const @This()) f32 { diff --git a/src/css/values/position.zig b/src/css/values/position.zig index 83c00b9692953d..d01085f1edf1a2 100644 --- a/src/css/values/position.zig +++ b/src/css/values/position.zig @@ -284,6 +284,10 @@ pub fn PositionComponent(comptime S: type) type { pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { return css.implementDeepClone(@This(), this, allocator); } + + pub fn eql(this: *const @This(), other: *const @This()) bool { + return css.implementEql(@This(), this, other); + } }, const This = @This(); @@ -298,20 +302,7 @@ pub fn PositionComponent(comptime S: type) type { } pub fn eql(this: *const This, other: *const This) bool { - return switch (this.*) { - .center => switch (other.*) { - .center => true, - else => false, - }, - .length => |*a| switch (other.*) { - .length => a.eql(&other.length), - else => false, - }, - .side => |*a| switch (other.*) { - .side => a.side.eql(&other.side.side) and css.generic.eql(?LengthPercentage, &a.offset, &other.side.offset), - else => false, - }, - }; + return css.implementEql(@This(), this, other); } pub fn parse(input: *css.Parser) Result(This) { diff --git a/src/css/values/resolution.zig b/src/css/values/resolution.zig index 951b809b21b8f5..cfe0f081f2a37e 100644 --- a/src/css/values/resolution.zig +++ b/src/css/values/resolution.zig @@ -39,20 +39,7 @@ pub const Resolution = union(enum) { } pub fn eql(this: *const Resolution, other: *const Resolution) bool { - return switch (this.*) { - .dpi => |*a| switch (other.*) { - .dpi => a.* == other.dpi, - else => false, - }, - .dpcm => |*a| switch (other.*) { - .dpcm => a.* == other.dpcm, - else => false, - }, - .dppx => |*a| switch (other.*) { - .dppx => a.* == other.dppx, - else => false, - }, - }; + return css.implementEql(@This(), this, other); } pub fn parse(input: *css.Parser) Result(Resolution) { diff --git a/src/css/values/time.zig b/src/css/values/time.zig index 23ed5c9f86dc2d..39d5b2210a9da5 100644 --- a/src/css/values/time.zig +++ b/src/css/values/time.zig @@ -28,7 +28,7 @@ const Ident = css.css_values.ident.Ident; /// /// Time values may be explicit or computed by `calc()`, but are always stored and serialized /// as their computed value. -pub const Time = union(enum) { +pub const Time = union(Tag) { /// A time in seconds. seconds: CSSNumber, /// A time in milliseconds. @@ -36,6 +36,10 @@ pub const Time = union(enum) { const Tag = enum(u8) { seconds = 1, milliseconds = 2 }; + pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() { + return css.implementDeepClone(@This(), this, allocator); + } + pub fn eql(lhs: *const @This(), rhs: *const @This()) bool { return css.implementEql(@This(), lhs, rhs); } @@ -44,19 +48,19 @@ pub const Time = union(enum) { } pub fn parse(input: *css.Parser) Result(Time) { - var calc_result = switch (input.tryParse(Calc(Time).parse, .{})) { - .result => |v| v, - .err => |e| return .{ .err = e }, - }; - switch (calc_result) { - .value => |v| { - const ret: Time = v.*; - // redundant allocation - calc_result.deinit(input.allocator()); - return .{ .result = ret }; + switch (input.tryParse(Calc(Time).parse, .{})) { + .result => |vv| switch (vv) { + .value => |v| { + const ret: Time = v.*; + // redundant allocation + var vvv = vv; + vvv.deinit(input.allocator()); + return .{ .result = ret }; + }, + // Time is always compatible, so they will always compute to a value. + else => return .{ .err = input.newErrorForNextToken() }, }, - // Time is always compatible, so they will always compute to a value. - else => return .{ .err = input.newErrorForNextToken() }, + .err => {}, } const location = input.currentSourceLocation(); @@ -67,14 +71,14 @@ pub const Time = union(enum) { switch (token.*) { .dimension => |*dim| { if (bun.strings.eqlCaseInsensitiveASCIIICheckLength("s", dim.unit)) { - return .{ .result = .{ .seconds = dim.value } }; + return .{ .result = .{ .seconds = dim.num.value } }; } else if (bun.strings.eqlCaseInsensitiveASCIIICheckLength("ms", dim.unit)) { - return .{ .result = .{ .milliseconds = dim.value } }; + return .{ .result = .{ .milliseconds = dim.num.value } }; } else { return .{ .err = location.newUnexpectedTokenError(css.Token{ .ident = dim.unit }) }; } }, - else => return .{ .err = location.newUnexpectedTokenError(token) }, + else => return .{ .err = location.newUnexpectedTokenError(token.*) }, } } @@ -103,6 +107,13 @@ pub const Time = union(enum) { } } + pub fn isZero(this: *const Time) bool { + return switch (this.*) { + .seconds => |s| s == 0.0, + .milliseconds => |ms| ms == 0.0, + }; + } + /// Returns the time in milliseconds. pub fn toMs(this: *const Time) CSSNumber { return switch (this.*) { @@ -138,11 +149,20 @@ pub const Time = union(enum) { }; } + pub fn addInternal(this: Time, allocator: std.mem.Allocator, other: Time) Time { + return this.add(allocator, other); + } + + pub fn intoCalc(this: Time, allocator: std.mem.Allocator) Calc(Time) { + return Calc(Time){ .value = bun.create(allocator, Time, this) }; + } + pub fn add(this: @This(), _: std.mem.Allocator, other: @This()) Time { - return switch (this) { - .seconds => |v| .{ .seconds = v + other.seconds }, - .milliseconds => |v| .{ .milliseconds = v + other.milliseconds }, - }; + return this.op(&other, {}, struct { + fn mul(_: void, a: f32, b: f32) f32 { + return a + b; + } + }.mul); } pub fn partialCmp(this: *const Time, other: *const Time) ?std.math.Order { diff --git a/src/darwin_c.zig b/src/darwin_c.zig index 744decef9d3ff1..c2d36a4648fdc7 100644 --- a/src/darwin_c.zig +++ b/src/darwin_c.zig @@ -66,7 +66,7 @@ pub const COPYFILE_CONTINUE = @as(c_int, 0); pub const COPYFILE_SKIP = @as(c_int, 1); pub const COPYFILE_QUIT = @as(c_int, 2); -pub extern "C" fn memmem(haystack: [*]const u8, haystacklen: usize, needle: [*]const u8, needlelen: usize) ?[*]const u8; +pub extern "c" fn memmem(haystack: [*]const u8, haystacklen: usize, needle: [*]const u8, needlelen: usize) ?[*]const u8; // int clonefileat(int src_dirfd, const char * src, int dst_dirfd, const char * dst, int flags); pub extern "c" fn clonefileat(c_int, [*:0]const u8, c_int, [*:0]const u8, uint32_t: c_int) c_int; @@ -77,16 +77,16 @@ pub extern "c" fn clonefile(src: [*:0]const u8, dest: [*:0]const u8, flags: c_in pub const lstat = blk: { const T = *const fn (?[*:0]const u8, ?*bun.Stat) callconv(.C) c_int; - break :blk @extern(T, .{ .name = "lstat64" }); + break :blk @extern(T, .{ .name = if (bun.Environment.isAarch64) "lstat" else "lstat64" }); }; pub const fstat = blk: { const T = *const fn (i32, ?*bun.Stat) callconv(.C) c_int; - break :blk @extern(T, .{ .name = "fstat64" }); + break :blk @extern(T, .{ .name = if (bun.Environment.isAarch64) "fstat" else "fstat64" }); }; pub const stat = blk: { const T = *const fn (?[*:0]const u8, ?*bun.Stat) callconv(.C) c_int; - break :blk @extern(T, .{ .name = "stat64" }); + break :blk @extern(T, .{ .name = if (bun.Environment.isAarch64) "stat" else "stat64" }); }; // pub fn stat_absolute(path: [:0]const u8) StatError!Stat { @@ -150,9 +150,9 @@ pub const stat = blk: { // else => Kind.Unknown, // }, // }, -// .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, -// .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, -// .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, +// .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, +// .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, +// .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, // }; // } @@ -473,16 +473,13 @@ pub fn getTotalMemory() u64 { return memory_[0]; } -pub const struct_BootTime = struct { - sec: u32, -}; pub fn getSystemUptime() u64 { - var uptime_: [16]struct_BootTime = undefined; - var size: usize = uptime_.len; + var boot_time: std.posix.timeval = undefined; + var size: usize = @sizeOf(@TypeOf(boot_time)); std.posix.sysctlbynameZ( "kern.boottime", - &uptime_, + &boot_time, &size, null, 0, @@ -490,20 +487,16 @@ pub fn getSystemUptime() u64 { else => return 0, }; - return @as(u64, @bitCast(std.time.timestamp() - uptime_[0].sec)); + return @intCast(std.time.timestamp() - boot_time.sec); } -pub const struct_LoadAvg = struct { - ldavg: [3]u32, - fscale: c_long, -}; pub fn getSystemLoadavg() [3]f64 { - var loadavg_: [24]struct_LoadAvg = undefined; - var size: usize = loadavg_.len; + var loadavg: bun.C.translated.struct_loadavg = undefined; + var size: usize = @sizeOf(@TypeOf(loadavg)); std.posix.sysctlbynameZ( "vm.loadavg", - &loadavg_, + &loadavg, &size, null, 0, @@ -511,8 +504,7 @@ pub fn getSystemLoadavg() [3]f64 { else => return [3]f64{ 0, 0, 0 }, }; - const loadavg = loadavg_[0]; - const scale = @as(f64, @floatFromInt(loadavg.fscale)); + const scale: f64 = @floatFromInt(loadavg.fscale); return .{ if (scale == 0.0) 0 else @as(f64, @floatFromInt(loadavg.ldavg[0])) / scale, if (scale == 0.0) 0 else @as(f64, @floatFromInt(loadavg.ldavg[1])) / scale, diff --git a/src/defines.zig b/src/defines.zig index f038248505ab35..f61508f3056cc7 100644 --- a/src/defines.zig +++ b/src/defines.zig @@ -85,7 +85,7 @@ pub const DefineData = struct { } pub fn fromMergeableInputEntry(user_defines: *UserDefines, key: []const u8, value_str: []const u8, value_is_undefined: bool, method_call_must_be_replaced_with_undefined: bool, log: *logger.Log, allocator: std.mem.Allocator) !void { - var keySplitter = std.mem.split(u8, key, "."); + var keySplitter = std.mem.splitScalar(u8, key, '.'); while (keySplitter.next()) |part| { if (!js_lexer.isIdentifier(part)) { if (strings.eql(part, key)) { @@ -98,7 +98,7 @@ pub const DefineData = struct { } // check for nested identifiers - var valueSplitter = std.mem.split(u8, value_str, "."); + var valueSplitter = std.mem.splitScalar(u8, value_str, '.'); var isIdent = true; while (valueSplitter.next()) |part| { @@ -217,7 +217,7 @@ pub const Define = struct { const remainder = key[0..last_dot]; const count = std.mem.count(u8, remainder, ".") + 1; var parts = try allocator.alloc(string, count + 1); - var splitter = std.mem.split(u8, remainder, "."); + var splitter = std.mem.splitScalar(u8, remainder, '.'); var i: usize = 0; while (splitter.next()) |split| : (i += 1) { parts[i] = split; diff --git a/src/deps/boringssl.translated.zig b/src/deps/boringssl.translated.zig index 60460ab810fcb7..dd88fbfd987c5b 100644 --- a/src/deps/boringssl.translated.zig +++ b/src/deps/boringssl.translated.zig @@ -18791,7 +18791,7 @@ pub extern fn ERR_get_next_error_library() c_int; pub const struct_bio_st = extern struct { method: [*c]const BIO_METHOD, - init: c_int, + _init: c_int, shutdown: c_int, flags: c_int, retry_reason: c_int, diff --git a/src/deps/c_ares.zig b/src/deps/c_ares.zig index 09c365a34c8614..5f8b945fae31b8 100644 --- a/src/deps/c_ares.zig +++ b/src/deps/c_ares.zig @@ -1433,7 +1433,7 @@ pub const struct_any_reply = struct { pub fn toJS(this: *struct_any_reply, globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator) JSC.JSValue { const array = JSC.JSValue.createEmptyArray(globalThis, blk: { var len: usize = 0; - inline for (comptime @typeInfo(struct_any_reply).Struct.fields) |field| { + inline for (comptime @typeInfo(struct_any_reply).@"struct".fields) |field| { if (comptime std.mem.endsWith(u8, field.name, "_reply")) { len += @intFromBool(@field(this, field.name) != null); } @@ -1443,7 +1443,7 @@ pub const struct_any_reply = struct { var i: u32 = 0; - inline for (comptime @typeInfo(struct_any_reply).Struct.fields) |field| { + inline for (comptime @typeInfo(struct_any_reply).@"struct".fields) |field| { if (comptime std.mem.endsWith(u8, field.name, "_reply")) { if (@field(this, field.name)) |reply| { const lookup_name = comptime field.name[0 .. field.name.len - "_reply".len]; @@ -1561,7 +1561,7 @@ pub const struct_any_reply = struct { } pub fn deinit(this: *struct_any_reply) void { - inline for (@typeInfo(struct_any_reply).Struct.fields) |field| { + inline for (@typeInfo(struct_any_reply).@"struct".fields) |field| { if (comptime std.mem.endsWith(u8, field.name, "_reply")) { if (@field(this, field.name)) |reply| { reply.deinit(); @@ -1993,7 +1993,7 @@ pub const ares_addr_port_node = struct_ares_addr_port_node; comptime { const Bun__canonicalizeIP = JSC.toJSHostFunction(Bun__canonicalizeIP_); - @export(Bun__canonicalizeIP, .{ .name = "Bun__canonicalizeIP" }); + @export(&Bun__canonicalizeIP, .{ .name = "Bun__canonicalizeIP" }); } pub fn Bun__canonicalizeIP_(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); diff --git a/src/deps/libuv.zig b/src/deps/libuv.zig index a07f095a2615ec..011be6e3823f35 100644 --- a/src/deps/libuv.zig +++ b/src/deps/libuv.zig @@ -2023,20 +2023,20 @@ pub const UV_CLOCK_MONOTONIC: c_int = 0; pub const UV_CLOCK_REALTIME: c_int = 1; pub const uv_clock_id = c_uint; pub const uv_timespec_t = extern struct { - tv_sec: c_long, - tv_nsec: c_long, + sec: c_long, + nsec: c_long, }; pub const uv_timespec64_t = extern struct { - tv_sec: i64, - tv_nsec: i32, + sec: i64, + nsec: i32, }; pub const uv_timeval_t = extern struct { - tv_sec: c_long, - tv_usec: c_long, + sec: c_long, + usec: c_long, }; pub const uv_timeval64_t = extern struct { - tv_sec: i64, - tv_usec: i32, + sec: i64, + usec: i32, }; pub const uv_stat_t = extern struct { dev: u64, diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 30b90a74048551..a56e2cbf3847fa 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -1,4 +1,3 @@ -pub const is_bindgen = false; const bun = @import("root").bun; const Api = bun.ApiSchema; const std = @import("std"); @@ -10,8 +9,10 @@ pub const u_int64_t = c_ulonglong; pub const LIBUS_LISTEN_DEFAULT: i32 = 0; pub const LIBUS_LISTEN_EXCLUSIVE_PORT: i32 = 1; pub const LIBUS_SOCKET_ALLOW_HALF_OPEN: i32 = 2; -pub const LIBUS_SOCKET_REUSE_PORT: i32 = 4; +pub const LIBUS_LISTEN_REUSE_PORT: i32 = 4; pub const LIBUS_SOCKET_IPV6_ONLY: i32 = 8; +pub const LIBUS_LISTEN_REUSE_ADDR: i32 = 16; +pub const LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE: i32 = 32; pub const Socket = opaque { pub fn write2(this: *Socket, first: []const u8, second: []const u8) i32 { @@ -19,7 +20,7 @@ pub const Socket = opaque { debug("us_socket_write2({d}, {d}) = {d}", .{ first.len, second.len, rc }); return rc; } - extern "C" fn us_socket_write2(ssl: i32, *Socket, header: ?[*]const u8, len: usize, payload: ?[*]const u8, usize) i32; + extern "c" fn us_socket_write2(ssl: i32, *Socket, header: ?[*]const u8, len: usize, payload: ?[*]const u8, usize) i32; }; pub const ConnectingSocket = opaque {}; const debug = bun.Output.scoped(.uws, false); @@ -1797,8 +1798,8 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { /// # Returns /// This function returns a slice of the buffer on success, or null on failure. pub fn localAddressText(this: ThisSocket, buf: []u8, is_ipv6: *bool) ?[]const u8 { - const addr_v4_len = @sizeOf(std.meta.FieldType(std.posix.sockaddr.in, .addr)); - const addr_v6_len = @sizeOf(std.meta.FieldType(std.posix.sockaddr.in6, .addr)); + const addr_v4_len = @sizeOf(@FieldType(std.posix.sockaddr.in, "addr")); + const addr_v6_len = @sizeOf(@FieldType(std.posix.sockaddr.in6, "addr")); var sa_buf: [addr_v6_len + 1]u8 = undefined; const binary = this.localAddressBinary(&sa_buf) orelse return null; @@ -2103,23 +2104,23 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { } }; - if (comptime @hasDecl(Type, "onOpen") and @typeInfo(@TypeOf(Type.onOpen)) != .Null) + if (comptime @hasDecl(Type, "onOpen") and @typeInfo(@TypeOf(Type.onOpen)) != .null) us_socket_context_on_open(ssl_int, ctx, SocketHandler.on_open); - if (comptime @hasDecl(Type, "onClose") and @typeInfo(@TypeOf(Type.onClose)) != .Null) + if (comptime @hasDecl(Type, "onClose") and @typeInfo(@TypeOf(Type.onClose)) != .null) us_socket_context_on_close(ssl_int, ctx, SocketHandler.on_close); - if (comptime @hasDecl(Type, "onData") and @typeInfo(@TypeOf(Type.onData)) != .Null) + if (comptime @hasDecl(Type, "onData") and @typeInfo(@TypeOf(Type.onData)) != .null) us_socket_context_on_data(ssl_int, ctx, SocketHandler.on_data); - if (comptime @hasDecl(Type, "onWritable") and @typeInfo(@TypeOf(Type.onWritable)) != .Null) + if (comptime @hasDecl(Type, "onWritable") and @typeInfo(@TypeOf(Type.onWritable)) != .null) us_socket_context_on_writable(ssl_int, ctx, SocketHandler.on_writable); - if (comptime @hasDecl(Type, "onTimeout") and @typeInfo(@TypeOf(Type.onTimeout)) != .Null) + if (comptime @hasDecl(Type, "onTimeout") and @typeInfo(@TypeOf(Type.onTimeout)) != .null) us_socket_context_on_timeout(ssl_int, ctx, SocketHandler.on_timeout); - if (comptime @hasDecl(Type, "onConnectError") and @typeInfo(@TypeOf(Type.onConnectError)) != .Null) { + if (comptime @hasDecl(Type, "onConnectError") and @typeInfo(@TypeOf(Type.onConnectError)) != .null) { us_socket_context_on_socket_connect_error(ssl_int, ctx, SocketHandler.on_connect_error); us_socket_context_on_connect_error(ssl_int, ctx, SocketHandler.on_connect_error_connecting_socket); } - if (comptime @hasDecl(Type, "onEnd") and @typeInfo(@TypeOf(Type.onEnd)) != .Null) + if (comptime @hasDecl(Type, "onEnd") and @typeInfo(@TypeOf(Type.onEnd)) != .null) us_socket_context_on_end(ssl_int, ctx, SocketHandler.on_end); - if (comptime @hasDecl(Type, "onHandshake") and @typeInfo(@TypeOf(Type.onHandshake)) != .Null) + if (comptime @hasDecl(Type, "onHandshake") and @typeInfo(@TypeOf(Type.onHandshake)) != .null) us_socket_context_on_handshake(ssl_int, ctx, SocketHandler.on_handshake, null); } @@ -2248,25 +2249,25 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { } }; - if (comptime @hasDecl(Type, "onOpen") and @typeInfo(@TypeOf(Type.onOpen)) != .Null) + if (comptime @hasDecl(Type, "onOpen") and @typeInfo(@TypeOf(Type.onOpen)) != .null) us_socket_context_on_open(ssl_int, ctx, SocketHandler.on_open); - if (comptime @hasDecl(Type, "onClose") and @typeInfo(@TypeOf(Type.onClose)) != .Null) + if (comptime @hasDecl(Type, "onClose") and @typeInfo(@TypeOf(Type.onClose)) != .null) us_socket_context_on_close(ssl_int, ctx, SocketHandler.on_close); - if (comptime @hasDecl(Type, "onData") and @typeInfo(@TypeOf(Type.onData)) != .Null) + if (comptime @hasDecl(Type, "onData") and @typeInfo(@TypeOf(Type.onData)) != .null) us_socket_context_on_data(ssl_int, ctx, SocketHandler.on_data); - if (comptime @hasDecl(Type, "onWritable") and @typeInfo(@TypeOf(Type.onWritable)) != .Null) + if (comptime @hasDecl(Type, "onWritable") and @typeInfo(@TypeOf(Type.onWritable)) != .null) us_socket_context_on_writable(ssl_int, ctx, SocketHandler.on_writable); - if (comptime @hasDecl(Type, "onTimeout") and @typeInfo(@TypeOf(Type.onTimeout)) != .Null) + if (comptime @hasDecl(Type, "onTimeout") and @typeInfo(@TypeOf(Type.onTimeout)) != .null) us_socket_context_on_timeout(ssl_int, ctx, SocketHandler.on_timeout); - if (comptime @hasDecl(Type, "onConnectError") and @typeInfo(@TypeOf(Type.onConnectError)) != .Null) { + if (comptime @hasDecl(Type, "onConnectError") and @typeInfo(@TypeOf(Type.onConnectError)) != .null) { us_socket_context_on_socket_connect_error(ssl_int, ctx, SocketHandler.on_connect_error); us_socket_context_on_connect_error(ssl_int, ctx, SocketHandler.on_connect_error_connecting_socket); } - if (comptime @hasDecl(Type, "onEnd") and @typeInfo(@TypeOf(Type.onEnd)) != .Null) + if (comptime @hasDecl(Type, "onEnd") and @typeInfo(@TypeOf(Type.onEnd)) != .null) us_socket_context_on_end(ssl_int, ctx, SocketHandler.on_end); - if (comptime @hasDecl(Type, "onHandshake") and @typeInfo(@TypeOf(Type.onHandshake)) != .Null) + if (comptime @hasDecl(Type, "onHandshake") and @typeInfo(@TypeOf(Type.onHandshake)) != .null) us_socket_context_on_handshake(ssl_int, ctx, SocketHandler.on_handshake, null); - if (comptime @hasDecl(Type, "onLongTimeout") and @typeInfo(@TypeOf(Type.onLongTimeout)) != .Null) + if (comptime @hasDecl(Type, "onLongTimeout") and @typeInfo(@TypeOf(Type.onLongTimeout)) != .null) us_socket_context_on_long_timeout(ssl_int, ctx, SocketHandler.on_long_timeout); } @@ -2641,9 +2642,8 @@ pub const us_bun_socket_context_options_t = extern struct { client_renegotiation_limit: u32 = 3, client_renegotiation_window: u32 = 600, }; -pub extern fn create_ssl_context_from_bun_options(options: us_bun_socket_context_options_t) ?*BoringSSL.SSL_CTX; -pub const create_bun_socket_error_t = enum(i32) { +pub const create_bun_socket_error_t = enum(c_int) { none = 0, load_ca_file, invalid_ca_file, @@ -2662,6 +2662,8 @@ pub const create_bun_socket_error_t = enum(i32) { } }; +pub extern fn create_ssl_context_from_bun_options(options: us_bun_socket_context_options_t, err: *create_bun_socket_error_t) ?*BoringSSL.SSL_CTX; + pub const us_bun_verify_error_t = extern struct { error_no: i32 = 0, code: [*c]const u8 = null, @@ -3370,10 +3372,6 @@ pub fn NewApp(comptime ssl: bool) type { } pub fn clearRoutes(app: *ThisApp) void { - if (comptime is_bindgen) { - unreachable; - } - return uws_app_clear_routes(ssl_flag, @as(*uws_app_t, @ptrCast(app))); } diff --git a/src/deps/zig-clap/clap.zig b/src/deps/zig-clap/clap.zig index cea034c1a7853b..8b128a24c9e9eb 100644 --- a/src/deps/zig-clap/clap.zig +++ b/src/deps/zig-clap/clap.zig @@ -69,7 +69,7 @@ pub fn parseParam(line: []const u8) !Param(Help) { @setEvalBranchQuota(999999); var found_comma = false; - var it = mem.tokenize(u8, line, " \t"); + var it = mem.tokenizeAny(u8, line, " \t"); var param_str = it.next() orelse return error.NoParamFound; const short_name = if (!mem.startsWith(u8, param_str, "--") and diff --git a/src/deps/zig-clap/clap/comptime.zig b/src/deps/zig-clap/clap/comptime.zig index 62d007c43b8cd9..cbd920952b2f7b 100644 --- a/src/deps/zig-clap/clap/comptime.zig +++ b/src/deps/zig-clap/clap/comptime.zig @@ -67,7 +67,7 @@ pub fn ComptimeClap( .passthrough_positionals = undefined, }; - var stream = clap.StreamingClap(usize, @typeInfo(@TypeOf(iter)).Pointer.child){ + var stream = clap.StreamingClap(usize, @typeInfo(@TypeOf(iter)).pointer.child){ .params = converted_params, .iter = iter, .diagnostic = opt.diagnostic, diff --git a/src/dns.zig b/src/dns.zig index c1d97920f264fb..1921e1428aa088 100644 --- a/src/dns.zig +++ b/src/dns.zig @@ -27,7 +27,7 @@ pub const GetAddrInfo = struct { hints.ai_family = this.options.family.toLibC(); hints.ai_socktype = this.options.socktype.toLibC(); hints.ai_protocol = this.options.protocol.toLibC(); - hints.ai_flags = this.options.flags; + hints.ai_flags = @bitCast(this.options.flags); return hints; } @@ -54,10 +54,10 @@ pub const GetAddrInfo = struct { socktype: SocketType = .stream, protocol: Protocol = .unspecified, backend: Backend = Backend.default, - flags: i32 = 0, + flags: std.c.AI = .{}, pub fn toLibC(this: Options) ?std.c.addrinfo { - if (this.family == .unspecified and this.socktype == .unspecified and this.protocol == .unspecified and this.flags == 0) { + if (this.family == .unspecified and this.socktype == .unspecified and this.protocol == .unspecified and this.flags == std.c.AI{}) { return null; } @@ -98,9 +98,9 @@ pub const GetAddrInfo = struct { if (!flags.isNumber()) return error.InvalidFlags; - options.flags = flags.coerce(i32, globalObject); + options.flags = flags.coerce(std.c.AI, globalObject); - if (options.flags & ~(AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED) != 0) + if (!options.flags.ALL and !options.flags.ADDRCONFIG and !options.flags.V4MAPPED) return error.InvalidFlags; } diff --git a/src/env_loader.zig b/src/env_loader.zig index 63646845276287..adb7cd8ac4264e 100644 --- a/src/env_loader.zig +++ b/src/env_loader.zig @@ -221,7 +221,7 @@ pub const Loader = struct { return http_proxy; } - var no_proxy_list = std.mem.split(u8, no_proxy_text, ","); + var no_proxy_list = std.mem.splitScalar(u8, no_proxy_text, ','); var next = no_proxy_list.next(); while (next != null) { var host = strings.trim(next.?, &strings.whitespace_chars); @@ -1163,11 +1163,11 @@ pub const Map = struct { map: HashTable, - pub fn createNullDelimitedEnvMap(this: *Map, arena: std.mem.Allocator) ![:null]?[*:0]u8 { + pub fn createNullDelimitedEnvMap(this: *Map, arena: std.mem.Allocator) ![:null]?[*:0]const u8 { var env_map = &this.map; const envp_count = env_map.count(); - const envp_buf = try arena.allocSentinel(?[*:0]u8, envp_count, null); + const envp_buf = try arena.allocSentinel(?[*:0]const u8, envp_count, null); { var it = env_map.iterator(); var i: usize = 0; diff --git a/src/fd.zig b/src/fd.zig index 5f9872255e7556..32b255e922df6d 100644 --- a/src/fd.zig +++ b/src/fd.zig @@ -238,7 +238,7 @@ pub const FDImpl = packed struct { const this_fmt = if (environment.isDebug) std.fmt.bufPrint(&buf, "{}", .{this}) catch unreachable; const result: ?bun.sys.Error = switch (environment.os) { - .linux => result: { + .linux, .mac => result: { const fd = this.encode(); bun.assert(fd != bun.invalid_fd); bun.assert(fd.cast() >= 0); @@ -247,15 +247,6 @@ pub const FDImpl = packed struct { else => null, }; }, - .mac => result: { - const fd = this.encode(); - bun.assert(fd != bun.invalid_fd); - bun.assert(fd.cast() >= 0); - break :result switch (bun.C.getErrno(bun.sys.syscall.@"close$NOCANCEL"(fd.cast()))) { - .BADF => bun.sys.Error{ .errno = @intFromEnum(posix.E.BADF), .syscall = .close, .fd = fd }, - else => null, - }; - }, .windows => result: { switch (this.kind) { .uv => { diff --git a/src/feature_flags.zig b/src/feature_flags.zig index 4def9f6352ed93..8b42968a31ba1e 100644 --- a/src/feature_flags.zig +++ b/src/feature_flags.zig @@ -62,7 +62,7 @@ pub const hardcode_localhost_to_127_0_0_1 = false; /// https://github.com/oven-sh/bun/issues/10733 pub const support_jsxs_in_jsx_transform = true; -pub const use_simdutf = bun.Environment.isNative and !bun.JSC.is_bindgen; +pub const use_simdutf = bun.Environment.isNative; pub const inline_properties_in_transpiler = true; diff --git a/src/fmt.zig b/src/fmt.zig index e946f2ae562df0..179c29a26ef0ff 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -1344,7 +1344,7 @@ pub fn quote(self: string) bun.fmt.QuotedFormatter { }; } -pub fn EnumTagListFormatter(comptime Enum: type, comptime Separator: @Type(.EnumLiteral)) type { +pub fn EnumTagListFormatter(comptime Enum: type, comptime Separator: @Type(.enum_literal)) type { return struct { pretty: bool = true, const output = brk: { @@ -1375,7 +1375,7 @@ pub fn EnumTagListFormatter(comptime Enum: type, comptime Separator: @Type(.Enum }; } -pub fn enumTagList(comptime Enum: type, comptime separator: @Type(.EnumLiteral)) EnumTagListFormatter(Enum, separator) { +pub fn enumTagList(comptime Enum: type, comptime separator: @Type(.enum_literal)) EnumTagListFormatter(Enum, separator) { return EnumTagListFormatter(Enum, separator){}; } diff --git a/src/futex.zig b/src/futex.zig index 24d66b056e69c4..546fd51547ec53 100644 --- a/src/futex.zig +++ b/src/futex.zig @@ -28,7 +28,7 @@ const atomic = std.atomic; /// The checking of `ptr` and `expect`, along with blocking the caller, is done atomically /// and totally ordered (sequentially consistent) with respect to other wait()/wake() calls on the same `ptr`. pub fn wait(ptr: *const atomic.Value(u32), expect: u32, timeout_ns: ?u64) error{Timeout}!void { - @setCold(true); + @branchHint(.cold); // Avoid calling into the OS for no-op timeouts. if (timeout_ns) |t| { @@ -42,7 +42,7 @@ pub fn wait(ptr: *const atomic.Value(u32), expect: u32, timeout_ns: ?u64) error{ } pub fn waitForever(ptr: *const atomic.Value(u32), expect: u32) void { - @setCold(true); + @branchHint(.cold); while (true) { Impl.wait(ptr, expect, null) catch |err| switch (err) { @@ -55,7 +55,7 @@ pub fn waitForever(ptr: *const atomic.Value(u32), expect: u32) void { /// Unblocks at most `max_waiters` callers blocked in a `wait()` call on `ptr`. pub fn wake(ptr: *const atomic.Value(u32), max_waiters: u32) void { - @setCold(true); + @branchHint(.cold); // Avoid calling into the OS if there's nothing to wake up. if (max_waiters == 0) { @@ -161,7 +161,7 @@ const DarwinImpl = struct { var timeout_overflowed = false; const addr: *const anyopaque = ptr; - const flags = c.UL_COMPARE_AND_WAIT | c.ULF_NO_ERRNO; + const flags: c.UL = .{ .op = .COMPARE_AND_WAIT, .NO_ERRNO = true }; const status = blk: { if (supports_ulock_wait2) { break :blk c.__ulock_wait2(flags, addr, expect, timeout_ns, 0); @@ -193,8 +193,8 @@ const DarwinImpl = struct { } fn wake(ptr: *const atomic.Value(u32), max_waiters: u32) void { - const default_flags: u32 = c.UL_COMPARE_AND_WAIT | c.ULF_NO_ERRNO; - const flags: u32 = default_flags | (if (max_waiters > 1) c.ULF_WAKE_ALL else @as(u32, 0)); + var flags: c.UL = .{ .op = .COMPARE_AND_WAIT, .NO_ERRNO = true }; + if (max_waiters > 1) flags.WAKE_ALL = true; while (true) { const addr: *const anyopaque = ptr; @@ -217,8 +217,8 @@ const LinuxImpl = struct { fn wait(ptr: *const atomic.Value(u32), expect: u32, timeout: ?u64) error{Timeout}!void { const ts: linux.timespec = if (timeout) |timeout_ns| .{ - .tv_sec = @intCast(timeout_ns / std.time.ns_per_s), - .tv_nsec = @intCast(timeout_ns % std.time.ns_per_s), + .sec = @intCast(timeout_ns / std.time.ns_per_s), + .nsec = @intCast(timeout_ns % std.time.ns_per_s), } else undefined; diff --git a/src/grapheme.zig b/src/grapheme.zig index 91a8c865e32677..2634c8d680a4f1 100644 --- a/src/grapheme.zig +++ b/src/grapheme.zig @@ -41,7 +41,7 @@ const Precompute = struct { var result: [std.math.maxInt(u10)]Value = undefined; @setEvalBranchQuota(2_000); - const info = @typeInfo(GraphemeBoundaryClass).Enum; + const info = @typeInfo(GraphemeBoundaryClass).@"enum"; for (0..std.math.maxInt(u2) + 1) |state_init| { for (info.fields) |field1| { for (info.fields) |field2| { diff --git a/src/http.zig b/src/http.zig index 3b4451c0cce36d..efb9255ba75e6c 100644 --- a/src/http.zig +++ b/src/http.zig @@ -50,13 +50,13 @@ const DeadSocket = opaque {}; var dead_socket = @as(*DeadSocket, @ptrFromInt(1)); //TODO: this needs to be freed when Worker Threads are implemented var socket_async_http_abort_tracker = std.AutoArrayHashMap(u32, uws.InternalSocket).init(bun.default_allocator); -var async_http_id: std.atomic.Value(u32) = std.atomic.Value(u32).init(0); +var async_http_id_monotonic: std.atomic.Value(u32) = std.atomic.Value(u32).init(0); const MAX_REDIRECT_URL_LENGTH = 128 * 1024; var custom_ssl_context_map = std.AutoArrayHashMap(*SSLConfig, *NewHTTPContext(true)).init(bun.default_allocator); pub var max_http_header_size: usize = 16 * 1024; comptime { - @export(max_http_header_size, .{ .name = "BUN_DEFAULT_MAX_HTTP_HEADER_SIZE" }); + @export(&max_http_header_size, .{ .name = "BUN_DEFAULT_MAX_HTTP_HEADER_SIZE" }); } const print_every = 0; @@ -235,7 +235,7 @@ const ProxyTunnel = struct { const ProxyTunnelWrapper = SSLWrapper(*HTTPClient); - usingnamespace bun.NewRefCounted(ProxyTunnel, ProxyTunnel.deinit); + usingnamespace bun.NewRefCounted(ProxyTunnel, _deinit, null); fn onOpen(this: *HTTPClient) void { this.state.response_stage = .proxy_handshake; @@ -520,7 +520,7 @@ const ProxyTunnel = struct { this.deref(); } - pub fn deinit(this: *ProxyTunnel) void { + fn _deinit(this: *ProxyTunnel) void { this.socket = .{ .none = {} }; if (this.wrapper) |*wrapper| { wrapper.deinit(); @@ -598,7 +598,7 @@ fn NewHTTPContext(comptime ssl: bool) type { } const ActiveSocket = TaggedPointerUnion(.{ - DeadSocket, + *DeadSocket, HTTPClient, PooledSocket, }); @@ -2462,13 +2462,11 @@ pub const AsyncHTTP = struct { } pub fn signalHeaderProgress(this: *AsyncHTTP) void { - @fence(.release); var progress = this.signals.header_progress orelse return; progress.store(true, .release); } pub fn enableBodyStreaming(this: *AsyncHTTP) void { - @fence(.release); var stream = this.signals.body_streaming orelse return; stream.store(true, .release); } @@ -2572,7 +2570,7 @@ pub const AsyncHTTP = struct { .result_callback = callback, .http_proxy = options.http_proxy, .signals = options.signals orelse .{}, - .async_http_id = if (options.signals != null and options.signals.?.aborted != null) async_http_id.fetchAdd(1, .monotonic) else 0, + .async_http_id = if (options.signals != null and options.signals.?.aborted != null) async_http_id_monotonic.fetchAdd(1, .monotonic) else 0, }; this.client = .{ @@ -3116,7 +3114,7 @@ pub const HTTPResponseMetadata = struct { }; fn printRequest(request: picohttp.Request, url: string, ignore_insecure: bool, body: []const u8, curl: bool) void { - @setCold(true); + @branchHint(.cold); var request_ = request; request_.path = url; @@ -3130,7 +3128,7 @@ fn printRequest(request: picohttp.Request, url: string, ignore_insecure: bool, b } fn printResponse(response: picohttp.Response) void { - @setCold(true); + @branchHint(.cold); Output.prettyErrorln("{}", .{response}); Output.flush(); } diff --git a/src/http/mime_type.zig b/src/http/mime_type.zig index a7cf32c5a990b7..1f284dc7ee4769 100644 --- a/src/http/mime_type.zig +++ b/src/http/mime_type.zig @@ -21,7 +21,7 @@ category: Category, pub const Map = bun.StringHashMap(MimeType); pub fn createHashTable(allocator: std.mem.Allocator) !Map { - @setCold(true); + @branchHint(.cold); const decls = comptime std.meta.declarations(all); diff --git a/src/http/websocket_http_client.zig b/src/http/websocket_http_client.zig index 734b795835dffc..66aa643d6bb9ce 100644 --- a/src/http/websocket_http_client.zig +++ b/src/http/websocket_http_client.zig @@ -161,7 +161,7 @@ const CppWebSocket = opaque { defer loop.exit(); WebSocket__didAbruptClose(this, reason); } - pub fn didClose(this: *CppWebSocket, code: u16, reason: *const bun.String) void { + pub fn didClose(this: *CppWebSocket, code: u16, reason: *bun.String) void { const loop = JSC.VirtualMachine.get().eventLoop(); loop.enter(); defer loop.exit(); @@ -226,7 +226,7 @@ pub fn NewHTTPUpgradeClient(comptime ssl: bool) type { pub const name = if (ssl) "WebSocketHTTPSClient" else "WebSocketHTTPClient"; pub const shim = JSC.Shimmer("Bun", name, @This()); - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); const HTTPClient = @This(); pub fn register(_: *JSC.JSGlobalObject, _: *anyopaque, ctx: *uws.SocketContext) callconv(.C) void { @@ -713,20 +713,18 @@ pub fn NewHTTPUpgradeClient(comptime ssl: bool) type { }); comptime { - if (!JSC.is_bindgen) { - @export(connect, .{ - .name = Export[0].symbol_name, - }); - @export(cancel, .{ - .name = Export[1].symbol_name, - }); - @export(register, .{ - .name = Export[2].symbol_name, - }); - @export(memoryCost, .{ - .name = Export[3].symbol_name, - }); - } + @export(&connect, .{ + .name = Export[0].symbol_name, + }); + @export(&cancel, .{ + .name = Export[1].symbol_name, + }); + @export(®ister, .{ + .name = Export[2].symbol_name, + }); + @export(&memoryCost, .{ + .name = Export[3].symbol_name, + }); } }; } @@ -1034,7 +1032,7 @@ pub fn NewWebSocketClient(comptime ssl: bool) type { const WebSocket = @This(); - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub fn register(global: *JSC.JSGlobalObject, loop_: *anyopaque, ctx_: *anyopaque) callconv(.C) void { const vm = global.bunVM(); const loop = @as(*uws.Loop, @ptrCast(@alignCast(loop_))); @@ -1846,7 +1844,7 @@ pub fn NewWebSocketClient(comptime ssl: bool) type { this.deref(); } - fn dispatchClose(this: *WebSocket, code: u16, reason: *const bun.String) void { + fn dispatchClose(this: *WebSocket, code: u16, reason: *bun.String) void { var out = this.outgoing_websocket orelse return; this.poll_ref.unref(this.globalThis.bunVM()); JSC.markBinding(@src()); @@ -2009,16 +2007,14 @@ pub fn NewWebSocketClient(comptime ssl: bool) type { }); comptime { - if (!JSC.is_bindgen) { - @export(writeBinaryData, .{ .name = Export[0].symbol_name }); - @export(writeString, .{ .name = Export[1].symbol_name }); - @export(close, .{ .name = Export[2].symbol_name }); - @export(cancel, .{ .name = Export[3].symbol_name }); - @export(register, .{ .name = Export[4].symbol_name }); - @export(init, .{ .name = Export[5].symbol_name }); - @export(finalize, .{ .name = Export[6].symbol_name }); - @export(memoryCost, .{ .name = Export[7].symbol_name }); - } + @export(&writeBinaryData, .{ .name = Export[0].symbol_name }); + @export(&writeString, .{ .name = Export[1].symbol_name }); + @export(&close, .{ .name = Export[2].symbol_name }); + @export(&cancel, .{ .name = Export[3].symbol_name }); + @export(®ister, .{ .name = Export[4].symbol_name }); + @export(&init, .{ .name = Export[5].symbol_name }); + @export(&finalize, .{ .name = Export[6].symbol_name }); + @export(&memoryCost, .{ .name = Export[7].symbol_name }); } }; } diff --git a/src/install/bin.zig b/src/install/bin.zig index 61bdf26ba427e3..4da91e8a0ba5cd 100644 --- a/src/install/bin.zig +++ b/src/install/bin.zig @@ -1,5 +1,5 @@ const ExternalStringList = @import("./install.zig").ExternalStringList; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const String = Semver.String; const Output = bun.Output; @@ -327,7 +327,7 @@ pub const Bin = extern struct { try writer.writeAll("{\n"); indent.* += 1; try writeIndent(writer, indent); - try writer.print("{}: {}\n", .{ + try writer.print("{}: {},\n", .{ this.value.named_file[0].fmtJson(buf, .{}), this.value.named_file[1].fmtJson(buf, .{}), }); @@ -339,23 +339,29 @@ pub const Bin = extern struct { try writer.print("{}", .{this.value.dir.fmtJson(buf, .{})}); }, .map => { - try writer.writeAll("{\n"); + try writer.writeByte('{'); indent.* += 1; const list = this.value.map.get(extern_strings); - var first = true; + var any = false; var i: usize = 0; while (i < list.len) : (i += 2) { - if (!first) { - try writer.writeByte(','); + if (!any) { + any = true; + try writer.writeByte('\n'); } try writeIndent(writer, indent); - first = false; - try writer.print("{}: {}", .{ + try writer.print("{}: {},\n", .{ list[i].value.fmtJson(buf, .{}), list[i + 1].value.fmtJson(buf, .{}), }); } + if (!any) { + try writer.writeByte('}'); + indent.* -= 1; + return; + } + indent.* -= 1; try writeIndent(writer, indent); try writer.writeByte('}'); @@ -364,7 +370,7 @@ pub const Bin = extern struct { } pub fn init() Bin { - return bun.serializable(.{ .tag = .none, .value = Value.init(.{ .none = {} }) }); + return bun.serializable(Bin{ .tag = .none, .value = Value.init(.{ .none = {} }) }); } pub const Value = extern union { diff --git a/src/install/bun.lock.zig b/src/install/bun.lock.zig index 9f9e7b40d90120..80e7702f774a5c 100644 --- a/src/install/bun.lock.zig +++ b/src/install/bun.lock.zig @@ -246,7 +246,7 @@ pub const Stringifier = struct { // _ = this; // } - pub fn saveFromBinary(allocator: std.mem.Allocator, lockfile: *const BinaryLockfile, writer: anytype) @TypeOf(writer).Error!void { + pub fn saveFromBinary(allocator: std.mem.Allocator, lockfile: *const BinaryLockfile, load_result: *const LoadResult, writer: anytype) @TypeOf(writer).Error!void { const buf = lockfile.buffers.string_bytes.items; const extern_strings = lockfile.buffers.extern_strings.items; const deps_buf = lockfile.buffers.dependencies.items; @@ -280,6 +280,32 @@ pub const Stringifier = struct { var optional_peers_buf = std.ArrayList(String).init(allocator); defer optional_peers_buf.deinit(); + var pkg_map = PkgMap(void).init(allocator); + defer pkg_map.deinit(); + + var pkgs_iter = BinaryLockfile.Tree.Iterator(.pkg_path).init(lockfile); + + var path_buf: bun.PathBuffer = undefined; + + // if we loaded from a binary lockfile and we're migrating it to a text lockfile, ensure + // peer dependencies have resolutions, and mark them optional if they don't + if (load_result.loadedFromBinaryLockfile()) { + while (pkgs_iter.next({})) |node| { + for (node.dependencies) |dep_id| { + const dep = deps_buf[dep_id]; + + // clobber, there isn't data + try pkg_map.put(try bun.fmt.allocPrint(allocator, "{s}{s}{s}", .{ + node.relative_path, + if (node.depth == 0) "" else "/", + dep.name.slice(buf), + }), {}); + } + } + + pkgs_iter.reset(); + } + var _indent: u32 = 0; const indent = &_indent; try writer.writeAll("{\n"); @@ -305,6 +331,9 @@ pub const Stringifier = struct { deps_buf, lockfile.workspace_versions, &optional_peers_buf, + &pkg_map, + "", + &path_buf, ); var workspace_sort_buf: std.ArrayListUnmanaged(PackageID) = .{}; @@ -353,6 +382,9 @@ pub const Stringifier = struct { deps_buf, lockfile.workspace_versions, &optional_peers_buf, + &pkg_map, + pkg_names[workspace_pkg_id].slice(buf), + &path_buf, ); } } @@ -377,8 +409,6 @@ pub const Stringifier = struct { var tree_sort_buf: std.ArrayListUnmanaged(TreeSortCtx.Item) = .{}; defer tree_sort_buf.deinit(allocator); - var pkgs_iter = BinaryLockfile.Tree.Iterator(.pkg_path).init(lockfile); - // find trusted and patched dependencies. also overrides while (pkgs_iter.next({})) |node| { try tree_sort_buf.append(allocator, .{ @@ -480,9 +510,9 @@ pub const Stringifier = struct { const name_and_version, const patch_path = value.*; try writeIndent(writer, indent); try writer.print( - \\"{s}": "{s}", + \\{}: {}, \\ - , .{ name_and_version, patch_path.slice(buf) }); + , .{ bun.fmt.formatJSONStringUTF8(name_and_version, .{}), patch_path.fmtJson(buf, .{}) }); } try decIndent(writer, indent); @@ -504,9 +534,9 @@ pub const Stringifier = struct { const name, const version = value.*; try writeIndent(writer, indent); try writer.print( - \\"{s}": "{s}", + \\{}: {}, \\ - , .{ name.slice(buf), version.literal.slice(buf) }); + , .{ name.fmtJson(buf, .{}), version.literal.fmtJson(buf, .{}) }); } try decIndent(writer, indent); @@ -634,7 +664,20 @@ pub const Stringifier = struct { res.value.folder.fmtJson(buf, .{ .quote = false }), }); - try writePackageInfoObject(writer, dep.behavior, deps_buf, pkg_deps_sort_buf.items, &pkg_meta, &pkg_bin, buf, &optional_peers_buf, extern_strings); + try writePackageInfoObject( + writer, + dep.behavior, + deps_buf, + pkg_deps_sort_buf.items, + &pkg_meta, + &pkg_bin, + buf, + &optional_peers_buf, + extern_strings, + &pkg_map, + relative_path, + &path_buf, + ); try writer.writeByte(']'); }, @@ -644,7 +687,20 @@ pub const Stringifier = struct { res.value.local_tarball.fmtJson(buf, .{ .quote = false }), }); - try writePackageInfoObject(writer, dep.behavior, deps_buf, pkg_deps_sort_buf.items, &pkg_meta, &pkg_bin, buf, &optional_peers_buf, extern_strings); + try writePackageInfoObject( + writer, + dep.behavior, + deps_buf, + pkg_deps_sort_buf.items, + &pkg_meta, + &pkg_bin, + buf, + &optional_peers_buf, + extern_strings, + &pkg_map, + relative_path, + &path_buf, + ); try writer.writeByte(']'); }, @@ -654,7 +710,20 @@ pub const Stringifier = struct { res.value.remote_tarball.fmtJson(buf, .{ .quote = false }), }); - try writePackageInfoObject(writer, dep.behavior, deps_buf, pkg_deps_sort_buf.items, &pkg_meta, &pkg_bin, buf, &optional_peers_buf, extern_strings); + try writePackageInfoObject( + writer, + dep.behavior, + deps_buf, + pkg_deps_sort_buf.items, + &pkg_meta, + &pkg_bin, + buf, + &optional_peers_buf, + extern_strings, + &pkg_map, + relative_path, + &path_buf, + ); try writer.writeByte(']'); }, @@ -664,7 +733,20 @@ pub const Stringifier = struct { res.value.symlink.fmtJson(buf, .{ .quote = false }), }); - try writePackageInfoObject(writer, dep.behavior, deps_buf, pkg_deps_sort_buf.items, &pkg_meta, &pkg_bin, buf, &optional_peers_buf, extern_strings); + try writePackageInfoObject( + writer, + dep.behavior, + deps_buf, + pkg_deps_sort_buf.items, + &pkg_meta, + &pkg_bin, + buf, + &optional_peers_buf, + extern_strings, + &pkg_map, + relative_path, + &path_buf, + ); try writer.writeByte(']'); }, @@ -682,7 +764,20 @@ pub const Stringifier = struct { res.value.npm.url.slice(buf), }); - try writePackageInfoObject(writer, dep.behavior, deps_buf, pkg_deps_sort_buf.items, &pkg_meta, &pkg_bin, buf, &optional_peers_buf, extern_strings); + try writePackageInfoObject( + writer, + dep.behavior, + deps_buf, + pkg_deps_sort_buf.items, + &pkg_meta, + &pkg_bin, + buf, + &optional_peers_buf, + extern_strings, + &pkg_map, + relative_path, + &path_buf, + ); try writer.print(", \"{}\"]", .{ pkg_meta.integrity, @@ -701,7 +796,20 @@ pub const Stringifier = struct { repo.fmt(if (comptime tag == .git) "git+" else "github:", buf), }); - try writePackageInfoObject(writer, dep.behavior, deps_buf, pkg_deps_sort_buf.items, &pkg_meta, &pkg_bin, buf, &optional_peers_buf, extern_strings); + try writePackageInfoObject( + writer, + dep.behavior, + deps_buf, + pkg_deps_sort_buf.items, + &pkg_meta, + &pkg_bin, + buf, + &optional_peers_buf, + extern_strings, + &pkg_map, + relative_path, + &path_buf, + ); try writer.print(", {}]", .{ repo.resolved.fmtJson(buf, .{}), @@ -734,6 +842,9 @@ pub const Stringifier = struct { buf: string, optional_peers_buf: *std.ArrayList(String), extern_strings: []const ExternalString, + pkg_map: *const PkgMap(void), + relative_path: string, + path_buf: []u8, ) OOM!void { defer optional_peers_buf.clearRetainingCapacity(); @@ -745,7 +856,7 @@ pub const Stringifier = struct { var first = true; for (pkg_dep_ids) |dep_id| { - const dep = deps_buf[dep_id]; + const dep = &deps_buf[dep_id]; if (!dep.behavior.includes(group_behavior)) continue; if (dep.behavior.isOptionalPeer()) { @@ -770,6 +881,12 @@ pub const Stringifier = struct { bun.fmt.formatJSONStringUTF8(dep.name.slice(buf), .{}), bun.fmt.formatJSONStringUTF8(dep.version.literal.slice(buf), .{}), }); + + if (dep.behavior.peer and !dep.behavior.optional and pkg_map.map.count() > 0) { + pkg_map.findResolution(relative_path, dep, buf, path_buf) catch { + try optional_peers_buf.append(dep.name); + }; + } } if (!first) { @@ -823,9 +940,7 @@ pub const Stringifier = struct { } else { any = true; } - try writer.writeAll( - \\ "os": - ); + try writer.writeAll(" \"os\": "); try Negatable(Npm.OperatingSystem).toJson(meta.os, writer); } @@ -835,9 +950,7 @@ pub const Stringifier = struct { } else { any = true; } - try writer.writeAll( - \\ "cpu": - ); + try writer.writeAll(" \"cpu\": "); try Negatable(Npm.Architecture).toJson(meta.arch, writer); } @@ -872,6 +985,9 @@ pub const Stringifier = struct { deps_buf: []const Dependency, workspace_versions: BinaryLockfile.VersionHashMap, optional_peers_buf: *std.ArrayList(String), + pkg_map: *const PkgMap(void), + relative_path: string, + path_buf: []u8, ) OOM!void { defer optional_peers_buf.clearRetainingCapacity(); // any - have any properties been written @@ -929,7 +1045,7 @@ pub const Stringifier = struct { const group_name, const group_behavior = group; var first = true; - for (pkg_deps[pkg_id].get(deps_buf)) |dep| { + for (pkg_deps[pkg_id].get(deps_buf)) |*dep| { if (!dep.behavior.includes(group_behavior)) continue; if (dep.behavior.isOptionalPeer()) { @@ -964,6 +1080,14 @@ pub const Stringifier = struct { bun.fmt.formatJSONStringUTF8(name, .{}), bun.fmt.formatJSONStringUTF8(version, .{}), }); + + if (dep.behavior.peer and !dep.behavior.optional and pkg_map.map.count() > 0) { + pkg_map.findResolution(relative_path, dep, buf, path_buf) catch |err| { + if (err == error.Unresolvable) { + try optional_peers_buf.append(dep.name); + } + }; + } } if (!first) { @@ -1026,10 +1150,10 @@ pub const Stringifier = struct { }; const workspace_dependency_groups = [4]struct { []const u8, Dependency.Behavior }{ - .{ "dependencies", Dependency.Behavior.prod }, - .{ "devDependencies", Dependency.Behavior.dev }, - .{ "optionalDependencies", Dependency.Behavior.optional }, - .{ "peerDependencies", Dependency.Behavior.peer }, + .{ "dependencies", .{ .prod = true } }, + .{ "devDependencies", .{ .dev = true } }, + .{ "optionalDependencies", .{ .optional = true } }, + .{ "peerDependencies", .{ .peer = true } }, }; const ParseError = OOM || error{ @@ -1061,6 +1185,104 @@ const PkgMapEntry = struct { bundled: bool, }; +fn PkgMap(comptime T: type) type { + return struct { + map: bun.StringArrayHashMap(T), + + pub const Entry = T; + + pub fn init(allocator: std.mem.Allocator) @This() { + return .{ + .map = bun.StringArrayHashMap(T).init(allocator), + }; + } + + pub fn deinit(this: *@This()) void { + this.map.deinit(); + } + + const ResolveError = error{ + InvalidPackageKey, + Unresolvable, + }; + + pub fn getOrPut(this: *@This(), name: string) OOM!@TypeOf(this.map).GetOrPutResult { + return this.map.getOrPut(name); + } + + pub fn put(this: *@This(), name: string, value: T) OOM!void { + return this.map.put(name, value); + } + + pub fn get(this: *const @This(), name: string) ?T { + return this.map.get(name); + } + + pub fn findResolution(this: *const @This(), pkg_path: string, dep: *const Dependency, string_buf: string, path_buf: []u8) ResolveError!T { + const dep_name = dep.name.slice(string_buf); + + @memcpy(path_buf[0..pkg_path.len], pkg_path); + path_buf[pkg_path.len] = '/'; + var offset = pkg_path.len + 1; + + var valid = true; + while (valid) { + @memcpy(path_buf[offset..][0..dep_name.len], dep_name); + const res_path = path_buf[0 .. offset + dep_name.len]; + + if (this.map.get(res_path)) |entry| { + return entry; + } + + if (offset == 0) { + return error.Unresolvable; + } + + const slash = strings.lastIndexOfChar(path_buf[0 .. offset - 1], '/') orelse { + offset = 0; + continue; + }; + + // might be a scoped package + const at = strings.lastIndexOfChar(path_buf[0 .. offset - 1], '@') orelse { + offset = slash + 1; + continue; + }; + + if (at > slash) { + valid = false; + continue; + } + + const next_slash = strings.lastIndexOfChar(path_buf[0..slash], '/') orelse { + if (at != 0) { + return error.InvalidPackageKey; + } + offset = 0; + continue; + }; + + if (next_slash > at) { + // there's a scoped package but it exists farther up + offset = slash + 1; + continue; + } + + if (next_slash + 1 != at) { + valid = false; + continue; + } + + offset = at; + } + + return error.InvalidPackageKey; + } + }; +} + +// const PkgMap = struct {}; + pub fn parseIntoBinaryLockfile( lockfile: *BinaryLockfile, allocator: std.mem.Allocator, @@ -1300,7 +1522,7 @@ pub fn parseIntoBinaryLockfile( const dep: Dependency = .{ .name = try string_buf.appendWithHash(name, name_hash), .name_hash = name_hash, - .behavior = Dependency.Behavior.workspace, + .behavior = .{ .workspace = true }, .version = .{ .tag = .workspace, .value = .{ @@ -1323,7 +1545,7 @@ pub fn parseIntoBinaryLockfile( try lockfile.getOrPutID(0, root_pkg.name_hash); } - var pkg_map = bun.StringArrayHashMap(PkgMapEntry).init(allocator); + var pkg_map = PkgMap(PkgMapEntry).init(allocator); defer pkg_map.deinit(); const workspace_pkgs_off: u32 = 1; @@ -1363,7 +1585,7 @@ pub fn parseIntoBinaryLockfile( } // there should be no duplicates - const pkg_id = try lockfile.appendPackageDedupe(&pkg, string_buf.bytes.items); + const pkg_id = try lockfile.appendPackageNoDedupe(&pkg, string_buf.bytes.items); const entry = try pkg_map.getOrPut(name); if (entry.found_existing) { @@ -1623,7 +1845,7 @@ pub fn parseIntoBinaryLockfile( pkg.name_hash = name_hash; pkg.resolution = res; - const pkg_id = try lockfile.appendPackageDedupe(&pkg, string_buf.bytes.items); + const pkg_id = try lockfile.appendPackageNoDedupe(&pkg, string_buf.bytes.items); const entry = try pkg_map.getOrPut(pkg_path); if (entry.found_existing) { @@ -1714,72 +1936,23 @@ pub fn parseIntoBinaryLockfile( const deps = pkg_deps[pkg_id]; deps: for (deps.begin()..deps.end()) |_dep_id| { const dep_id: DependencyID = @intCast(_dep_id); - var dep = &lockfile.buffers.dependencies.items[dep_id]; - const dep_name = dep.name.slice(lockfile.buffers.string_bytes.items); - - @memcpy(path_buf[0..pkg_path.len], pkg_path); - path_buf[pkg_path.len] = '/'; - var offset = pkg_path.len + 1; - - var valid = true; - while (valid) { - @memcpy(path_buf[offset..][0..dep_name.len], dep_name); - const res_path = path_buf[0 .. offset + dep_name.len]; - - if (pkg_map.get(res_path)) |entry| { - mapDepToPkg(dep, dep_id, &entry, lockfile, pkg_resolutions); - continue :deps; - } + const dep = &lockfile.buffers.dependencies.items[dep_id]; - if (offset == 0) { + const entry = pkg_map.findResolution(pkg_path, dep, lockfile.buffers.string_bytes.items, &path_buf) catch |err| switch (err) { + error.InvalidPackageKey => { + try log.addError(source, key.loc, "Invalid package path"); + return error.InvalidPackageKey; + }, + error.Unresolvable => { if (dep.behavior.optional) { continue :deps; } try dependencyResolutionFailure(dep, pkg_path, allocator, lockfile.buffers.string_bytes.items, source, log, key.loc); return error.InvalidPackageInfo; - } - - const slash = strings.lastIndexOfChar(path_buf[0 .. offset - 1], '/') orelse { - offset = 0; - continue; - }; - - // might be a scoped package - const at = strings.lastIndexOfChar(path_buf[0 .. offset - 1], '@') orelse { - offset = slash + 1; - continue; - }; - - if (at > slash) { - valid = false; - continue; - } - - const next_slash = strings.lastIndexOfChar(path_buf[0..slash], '/') orelse { - if (at != 0) { - try log.addError(source, key.loc, "Invalid package path"); - return error.InvalidPackageKey; - } - offset = 0; - continue; - }; - - if (next_slash > at) { - // there's a scoped package but it exists farther up - offset = slash + 1; - continue; - } - - if (next_slash + 1 != at) { - valid = false; - continue; - } - - offset = at; - } + }, + }; - try log.addError(source, key.loc, "Invalid package path"); - return error.InvalidPackageKey; + mapDepToPkg(dep, dep_id, &entry, lockfile, pkg_resolutions); } } diff --git a/src/install/dependency.zig b/src/install/dependency.zig index 4ded9d5682eb59..1f606b39cef188 100644 --- a/src/install/dependency.zig +++ b/src/install/dependency.zig @@ -7,7 +7,7 @@ const ExternalStringList = Install.ExternalStringList; const Features = Install.Features; const PackageNameHash = Install.PackageNameHash; const Repository = @import("./repository.zig").Repository; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const SlicedString = Semver.SlicedString; const String = Semver.String; @@ -1258,7 +1258,7 @@ pub fn fromJS(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JS if (!alias_value.isString()) { return .undefined; } - const alias_slice = alias_value.toSlice(globalThis, allocator); + const alias_slice = try alias_value.toSlice(globalThis, allocator); defer alias_slice.deinit(); if (alias_slice.len == 0) { @@ -1266,7 +1266,7 @@ pub fn fromJS(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JS } const name_value = if (arguments.len > 1) arguments[1] else .undefined; - const name_slice = name_value.toSlice(globalThis, allocator); + const name_slice = try name_value.toSlice(globalThis, allocator); defer name_slice.deinit(); var name = alias_slice.slice(); @@ -1311,12 +1311,6 @@ pub const Behavior = packed struct(u8) { bundled: bool = false, _unused_2: u1 = 0, - pub const prod = Behavior{ .prod = true }; - pub const optional = Behavior{ .optional = true }; - pub const dev = Behavior{ .dev = true }; - pub const peer = Behavior{ .peer = true }; - pub const workspace = Behavior{ .workspace = true }; - pub inline fn isProd(this: Behavior) bool { return this.prod; } @@ -1357,13 +1351,13 @@ pub const Behavior = packed struct(u8) { return @as(u8, @bitCast(lhs)) & @as(u8, @bitCast(rhs)) != 0; } - pub inline fn add(this: Behavior, kind: @Type(.EnumLiteral)) Behavior { + pub inline fn add(this: Behavior, kind: @Type(.enum_literal)) Behavior { var new = this; @field(new, @tagName(kind)) = true; return new; } - pub inline fn set(this: Behavior, kind: @Type(.EnumLiteral), value: bool) Behavior { + pub inline fn set(this: Behavior, kind: @Type(.enum_literal), value: bool) Behavior { var new = this; @field(new, @tagName(kind)) = value; return new; @@ -1425,10 +1419,10 @@ pub const Behavior = packed struct(u8) { } comptime { - bun.assert(@as(u8, @bitCast(Behavior.prod)) == (1 << 1)); - bun.assert(@as(u8, @bitCast(Behavior.optional)) == (1 << 2)); - bun.assert(@as(u8, @bitCast(Behavior.dev)) == (1 << 3)); - bun.assert(@as(u8, @bitCast(Behavior.peer)) == (1 << 4)); - bun.assert(@as(u8, @bitCast(Behavior.workspace)) == (1 << 5)); + bun.assert(@as(u8, @bitCast(Behavior{ .prod = true })) == (1 << 1)); + bun.assert(@as(u8, @bitCast(Behavior{ .optional = true })) == (1 << 2)); + bun.assert(@as(u8, @bitCast(Behavior{ .dev = true })) == (1 << 3)); + bun.assert(@as(u8, @bitCast(Behavior{ .peer = true })) == (1 << 4)); + bun.assert(@as(u8, @bitCast(Behavior{ .workspace = true })) == (1 << 5)); } }; diff --git a/src/install/extract_tarball.zig b/src/install/extract_tarball.zig index e8b8fb0c481d88..ef78639e45e146 100644 --- a/src/install/extract_tarball.zig +++ b/src/install/extract_tarball.zig @@ -11,7 +11,7 @@ const PackageManager = Install.PackageManager; const Integrity = @import("./integrity.zig").Integrity; const Npm = @import("./npm.zig"); const Resolution = @import("./resolution.zig").Resolution; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const std = @import("std"); const string = @import("../string_types.zig").string; const strings = @import("../string_immutable.zig"); diff --git a/src/install/install.zig b/src/install/install.zig index 0aae26874ea438..40f4932fd78754 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -145,7 +145,7 @@ const IdentityContext = @import("../identity_context.zig").IdentityContext; const ArrayIdentityContext = @import("../identity_context.zig").ArrayIdentityContext; const NetworkQueue = std.fifo.LinearFifo(*NetworkTask, .{ .Static = 32 }); const PatchTaskFifo = std.fifo.LinearFifo(*PatchTask, .{ .Static = 32 }); -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const String = Semver.String; const GlobalStringBuilder = @import("../string_builder.zig"); @@ -715,7 +715,7 @@ pub const Task = struct { if (pt.callback.apply.logger.errors > 0) { defer pt.callback.apply.logger.deinit(); // this.log.addErrorFmt(null, logger.Loc.Empty, bun.default_allocator, "failed to apply patch: {}", .{e}) catch unreachable; - pt.callback.apply.logger.print(Output.writer()) catch {}; + pt.callback.apply.logger.print(Output.errorWriter()) catch {}; } } } @@ -1316,7 +1316,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { pub const Result = union(Tag) { success: void, - fail: struct { + failure: struct { err: anyerror, step: Step, debug_trace: if (Environment.isDebug) bun.crash_handler.StoredTrace else void, @@ -1326,13 +1326,10 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { } }, - pub inline fn success() Result { - return .{ .success = {} }; - } - + /// Init a Result with the 'fail' tag. use `.success` for the 'success' tag. pub inline fn fail(err: anyerror, step: Step, trace: ?*std.builtin.StackTrace) Result { return .{ - .fail = .{ + .failure = .{ .err = err, .step = step, .debug_trace = if (Environment.isDebug) @@ -1347,13 +1344,13 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { pub fn isFail(this: @This()) bool { return switch (this) { .success => false, - .fail => true, + .failure => true, }; } pub const Tag = enum { success, - fail, + failure, }; }; @@ -1540,10 +1537,10 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { state.walker.deinit(); return Result.fail(err, .opening_dest_dir, @errorReturnTrace()); }; - return Result.success(); + return .success; } - const dest_path_length = bun.windows.kernel32.GetFinalPathNameByHandleW(destbase.fd, &state.buf, state.buf.len, 0); + const dest_path_length = bun.windows.GetFinalPathNameByHandleW(destbase.fd, &state.buf, state.buf.len, 0); if (dest_path_length == 0) { const e = bun.windows.Win32Error.get(); const err = if (e.toSystemErrno()) |sys_err| bun.errnoToZigErr(sys_err) else error.Unexpected; @@ -1567,7 +1564,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { _ = node_fs_for_package_installer.mkdirRecursiveOSPathImpl(void, {}, fullpath, 0, false); state.to_copy_buf = state.buf[fullpath.len..]; - const cache_path_length = bun.windows.kernel32.GetFinalPathNameByHandleW(state.cached_package_dir.fd, &state.buf2, state.buf2.len, 0); + const cache_path_length = bun.windows.GetFinalPathNameByHandleW(state.cached_package_dir.fd, &state.buf2, state.buf2.len, 0); if (cache_path_length == 0) { const e = bun.windows.Win32Error.get(); const err = if (e.toSystemErrno()) |sys_err| bun.errnoToZigErr(sys_err) else error.Unexpected; @@ -1585,7 +1582,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { } state.to_copy_buf2 = to_copy_buf2; - return Result.success(); + return .success; } fn installWithCopyfile(this: *@This(), destination_dir: std.fs.Dir) Result { @@ -1715,7 +1712,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { if (Environment.isWindows) &state.buf2 else void{}, ) catch |err| return Result.fail(err, .copying_files, @errorReturnTrace()); - return Result.success(); + return .success; } fn NewTaskQueue(comptime TaskType: type) type { @@ -1726,7 +1723,6 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { wake_value: std.atomic.Value(u32) = std.atomic.Value(u32).init(0), pub fn completeOne(this: *@This()) void { - @fence(.release); if (this.remaining.fetchSub(1, .monotonic) == 1) { _ = this.wake_value.fetchAdd(1, .monotonic); bun.Futex.wake(&this.wake_value, std.math.maxInt(u32)); @@ -1739,7 +1735,6 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { } pub fn wait(this: *@This()) void { - @fence(.acquire); this.wake_value.store(0, .monotonic); while (this.remaining.load(.monotonic) > 0) { bun.Futex.wait(&this.wake_value, 0, std.time.ns_per_ms * 5) catch {}; @@ -1963,7 +1958,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { return Result.fail(err, .copying_files, @errorReturnTrace()); }; - return Result.success(); + return .success; } fn installWithSymlink(this: *@This(), dest_dir: std.fs.Dir) !Result { @@ -2103,7 +2098,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { return Result.fail(err, .copying_files, @errorReturnTrace()); }; - return Result.success(); + return .success; } pub fn uninstall(this: *@This(), destination_dir: std.fs.Dir) void { @@ -2263,7 +2258,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { // When we're linking on Windows, we want to avoid keeping the source directory handle open if (comptime Environment.isWindows) { var wbuf: bun.WPathBuffer = undefined; - const dest_path_length = bun.windows.kernel32.GetFinalPathNameByHandleW(destination_dir.fd, &wbuf, dest_buf.len, 0); + const dest_path_length = bun.windows.GetFinalPathNameByHandleW(destination_dir.fd, &wbuf, dest_buf.len, 0); if (dest_path_length == 0) { const e = bun.windows.Win32Error.get(); const err = if (e.toSystemErrno()) |sys_err| bun.errnoToZigErr(sys_err) else error.Unexpected; @@ -2334,7 +2329,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { if (isDanglingSymlink(symlinked_path)) return Result.fail(error.DanglingSymlink, .linking_dependency, @errorReturnTrace()); - return Result.success(); + return .success; } pub fn getInstallMethod(this: *const @This()) Method { @@ -2402,12 +2397,12 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { const fd = bun.toFD(destination_dir.fd); const subpath = bun.path.joinZ(&[_][]const u8{ this.destination_dir_subpath, ".bun-patch-tag" }); const tag_fd = switch (bun.sys.openat(fd, subpath, bun.O.CREAT | bun.O.WRONLY, 0o666)) { - .err => |e| return .{ .fail = .{ .err = bun.errnoToZigErr(e.getErrno()), .step = Step.patching } }, + .err => |e| return .fail(bun.errnoToZigErr(e.getErrno()), .patching, @errorReturnTrace()), .result => |f| f, }; defer _ = bun.sys.close(tag_fd); - if (bun.sys.File.writeAll(.{ .handle = tag_fd }, this.package_version).asErr()) |e| return .{ .fail = .{ .err = bun.errnoToZigErr(e.getErrno()), .step = Step.patching } }; + if (bun.sys.File.writeAll(.{ .handle = tag_fd }, this.package_version).asErr()) |e| return .fail(bun.errnoToZigErr(e.getErrno()), .patching, @errorReturnTrace()); } pub fn installImpl(this: *@This(), skip_delete: bool, destination_dir: std.fs.Dir, method_: Method, resolution_tag: Resolution.Tag) Result { @@ -2486,7 +2481,7 @@ pub fn NewPackageInstall(comptime kind: PkgInstallKind) type { else => {}, } - if (supported_method_to_use != .copyfile) return Result.success(); + if (supported_method_to_use != .copyfile) return .success; // TODO: linux io_uring return this.installWithCopyfile(destination_dir); @@ -7801,10 +7796,10 @@ pub const PackageManager = struct { const trusted_dependencies_string = "trustedDependencies"; const dependency_groups = &.{ - .{ "optionalDependencies", Dependency.Behavior.optional }, - .{ "devDependencies", Dependency.Behavior.dev }, - .{ "dependencies", Dependency.Behavior.prod }, - .{ "peerDependencies", Dependency.Behavior.peer }, + .{ "optionalDependencies", .{ .optional = true } }, + .{ "devDependencies", .{ .dev = true } }, + .{ "dependencies", .{ .prod = true } }, + .{ "peerDependencies", .{ .peer = true } }, }; pub const EditOptions = struct { @@ -11628,7 +11623,7 @@ pub const PackageManager = struct { var out_dir: if (bun.Environment.isWindows) []const u16 else void = undefined; if (comptime bun.Environment.isWindows) { - const inlen = bun.windows.kernel32.GetFinalPathNameByHandleW(pkg_in_cache_dir.fd, &buf1, buf1.len, 0); + const inlen = bun.windows.GetFinalPathNameByHandleW(pkg_in_cache_dir.fd, &buf1, buf1.len, 0); if (inlen == 0) { const e = bun.windows.Win32Error.get(); const err = if (e.toSystemErrno()) |sys_err| bun.errnoToZigErr(sys_err) else error.Unexpected; @@ -11636,7 +11631,7 @@ pub const PackageManager = struct { Global.crash(); } in_dir = buf1[0..inlen]; - const outlen = bun.windows.kernel32.GetFinalPathNameByHandleW(node_modules_folder.fd, &buf2, buf2.len, 0); + const outlen = bun.windows.GetFinalPathNameByHandleW(node_modules_folder.fd, &buf2, buf2.len, 0); if (outlen == 0) { const e = bun.windows.Win32Error.get(); const err = if (e.toSystemErrno()) |sys_err| bun.errnoToZigErr(sys_err) else error.Unexpected; @@ -12193,7 +12188,7 @@ pub const PackageManager = struct { const ESCAPE_TABLE: [256]EscapeVal = comptime brk: { var table: [256]EscapeVal = [_]EscapeVal{.other} ** 256; const ty = @typeInfo(EscapeVal); - for (ty.Enum.fields) |field| { + for (ty.@"enum".fields) |field| { if (field.name.len == 1) { const c = field.name[0]; table[c] = @enumFromInt(field.value); @@ -12234,7 +12229,7 @@ pub const PackageManager = struct { Output.prettyln("bun add v" ++ Global.package_json_version_with_sha ++ "\n", .{}); Output.flush(); } - return try switch (manager.options.log_level) { + return switch (manager.options.log_level) { inline else => |log_level| manager.updatePackageJSONAndInstallWithManager(ctx, original_cwd, log_level), }; } @@ -13368,7 +13363,7 @@ pub const PackageManager = struct { var lazy_package_dir: LazyPackageDestinationDir = .{ .dir = destination_dir }; - const install_result = switch (resolution.tag) { + const install_result: PackageInstall.Result = switch (resolution.tag) { .symlink, .workspace => installer.installFromLink(this.skip_delete, destination_dir), else => result: { if (resolution.tag == .root or (resolution.tag == .folder and !this.lockfile.isWorkspaceTreeId(this.current_tree_id))) { @@ -13377,15 +13372,15 @@ pub const PackageManager = struct { const dirname = std.fs.path.dirname(this.node_modules.path.items) orelse this.node_modules.path.items; installer.cache_dir = this.root_node_modules_folder.openDir(dirname, .{ .iterate = true, .access_sub_paths = true }) catch |err| - break :result PackageInstall.Result.fail(err, .opening_cache_dir, @errorReturnTrace()); + break :result .fail(err, .opening_cache_dir, @errorReturnTrace()); const result = if (resolution.tag == .root) installer.installFromLink(this.skip_delete, destination_dir) else installer.install(this.skip_delete, destination_dir, resolution.tag); - if (result.isFail() and (result.fail.err == error.ENOENT or result.fail.err == error.FileNotFound)) - break :result PackageInstall.Result.success(); + if (result.isFail() and (result.failure.err == error.ENOENT or result.failure.err == error.FileNotFound)) + break :result .success; break :result result; } @@ -13468,7 +13463,7 @@ pub const PackageManager = struct { if (!pkg_has_patch) this.incrementTreeInstallCount(this.current_tree_id, &lazy_package_dir, !is_pending_package_install, log_level); }, - .fail => |cause| { + .failure => |cause| { if (comptime Environment.allow_assert) { bun.assert(!cause.isPackageMissingFromCache() or (resolution.tag != .symlink and resolution.tag != .workspace)); } @@ -13537,7 +13532,7 @@ pub const PackageManager = struct { cause.err, "failed {s} for package {s}", .{ - install_result.fail.step.name(), + install_result.failure.step.name(), this.names[package_id].slice(this.lockfile.buffers.string_bytes.items), }, ); @@ -15000,7 +14995,7 @@ pub const PackageManager = struct { const lockfile_before_install = manager.lockfile; - const save_format = load_result.saveFormat(manager); + const save_format = load_result.saveFormat(&manager.options); if (manager.options.lockfile_only) { // save the lockfile and exit. make sure metahash is generated for binary lockfile @@ -15015,10 +15010,7 @@ pub const PackageManager = struct { if (manager.options.do.summary) { // TODO(dylan-conway): packages aren't installed but we can still print // added/removed/updated direct dependencies. - Output.pretty( - \\ - \\Saved {s} ({d} package{s}) - , .{ + Output.pretty("\nSaved {s} ({d} package{s}) ", .{ switch (save_format) { .text => "bun.lock", .binary => "bun.lockb", @@ -15338,7 +15330,7 @@ pub const PackageManager = struct { this.progress.refresh(); } - this.lockfile.saveToDisk(save_format, this.options.log_level.isVerbose()); + this.lockfile.saveToDisk(load_result, &this.options); // delete binary lockfile if saving text lockfile if (save_format == .text and load_result.loadedFromBinaryLockfile()) { diff --git a/src/install/lifecycle_script_runner.zig b/src/install/lifecycle_script_runner.zig index 42c71494eae16f..52f10c548c5209 100644 --- a/src/install/lifecycle_script_runner.zig +++ b/src/install/lifecycle_script_runner.zig @@ -27,7 +27,7 @@ pub const LifecycleScriptSubprocess = struct { stderr: OutputReader = OutputReader.init(@This()), has_called_process_exit: bool = false, manager: *PackageManager, - envp: [:null]?[*:0]u8, + envp: [:null]?[*:0]const u8, timer: ?Timer = null, @@ -484,7 +484,7 @@ pub const LifecycleScriptSubprocess = struct { pub fn spawnPackageScripts( manager: *PackageManager, list: Lockfile.Package.Scripts.List, - envp: [:null]?[*:0]u8, + envp: [:null]?[*:0]const u8, optional: bool, comptime log_level: PackageManager.Options.LogLevel, comptime foreground: bool, diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index 90f3532153b25b..4d97df2737b134 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -56,7 +56,7 @@ const Lockfile = @This(); const IdentityContext = @import("../identity_context.zig").IdentityContext; const ArrayIdentityContext = @import("../identity_context.zig").ArrayIdentityContext; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const String = Semver.String; const GlobalStringBuilder = @import("../string_builder.zig"); @@ -259,17 +259,17 @@ pub const LoadResult = union(enum) { }; } - pub fn saveFormat(this: LoadResult, manager: *const PackageManager) LockfileFormat { + pub fn saveFormat(this: LoadResult, options: *const PackageManager.Options) LockfileFormat { switch (this) { .not_found => { // saving a lockfile for a new project. default to text lockfile // unless saveTextLockfile is false in bunfig - const save_text_lockfile = manager.options.save_text_lockfile orelse true; + const save_text_lockfile = options.save_text_lockfile orelse true; return if (save_text_lockfile) .text else .binary; }, .err => |err| { // an error occured, but we still loaded from an existing lockfile - if (manager.options.save_text_lockfile) |save_text_lockfile| { + if (options.save_text_lockfile) |save_text_lockfile| { if (save_text_lockfile) { return .text; } @@ -278,7 +278,7 @@ pub const LoadResult = union(enum) { }, .ok => |ok| { // loaded from an existing lockfile - if (manager.options.save_text_lockfile) |save_text_lockfile| { + if (options.save_text_lockfile) |save_text_lockfile| { if (save_text_lockfile) { return .text; } @@ -429,7 +429,7 @@ pub fn loadFromDir( var buffered_writer = writer_buf.bufferedWriter(); const writer = buffered_writer.writer(); - TextLockfile.Stringifier.saveFromBinary(allocator, result.ok.lockfile, writer) catch |err| { + TextLockfile.Stringifier.saveFromBinary(allocator, result.ok.lockfile, &result, writer) catch |err| { Output.panic("failed to convert binary lockfile to text lockfile: {s}", .{@errorName(err)}); }; @@ -1704,7 +1704,7 @@ pub const Printer = struct { input_lockfile_path: string, format: Format, ) !void { - @setCold(true); + @branchHint(.cold); // We truncate longer than allowed paths. We should probably throw an error instead. const path = input_lockfile_path[0..@min(input_lockfile_path.len, bun.MAX_PATH_BYTES)]; @@ -2504,7 +2504,8 @@ pub fn verifyData(this: *const Lockfile) !void { } } -pub fn saveToDisk(this: *Lockfile, save_format: LoadResult.LockfileFormat, verbose_log: bool) void { +pub fn saveToDisk(this: *Lockfile, load_result: *const LoadResult, options: *const PackageManager.Options) void { + const save_format = load_result.saveFormat(options); if (comptime Environment.allow_assert) { this.verifyData() catch |err| { Output.prettyErrorln("error: failed to verify lockfile: {s}", .{@errorName(err)}); @@ -2519,7 +2520,7 @@ pub fn saveToDisk(this: *Lockfile, save_format: LoadResult.LockfileFormat, verbo var buffered_writer = writer_buf.bufferedWriter(); const writer = buffered_writer.writer(); - TextLockfile.Stringifier.saveFromBinary(bun.default_allocator, this, writer) catch |err| switch (err) { + TextLockfile.Stringifier.saveFromBinary(bun.default_allocator, this, load_result, writer) catch |err| switch (err) { error.OutOfMemory => bun.outOfMemory(), }; @@ -2534,7 +2535,7 @@ pub fn saveToDisk(this: *Lockfile, save_format: LoadResult.LockfileFormat, verbo var total_size: usize = 0; var end_pos: usize = 0; - Lockfile.Serializer.save(this, verbose_log, &bytes, &total_size, &end_pos) catch |err| { + Lockfile.Serializer.save(this, options.log_level.isVerbose(), &bytes, &total_size, &end_pos) catch |err| { Output.err(err, "failed to serialize lockfile", .{}); Global.crash(); }; @@ -2686,8 +2687,8 @@ pub fn getPackageID( return null; } -/// Appends `pkg` to `this.packages` if a duplicate isn't found -pub fn appendPackageDedupe(this: *Lockfile, pkg: *Package, buf: string) OOM!PackageID { +/// Appends `pkg` to `this.packages`, and adds to `this.package_index` +pub fn appendPackageNoDedupe(this: *Lockfile, pkg: *Package, buf: string) OOM!PackageID { const entry = try this.package_index.getOrPut(pkg.name_hash); if (!entry.found_existing) { @@ -2702,11 +2703,6 @@ pub fn appendPackageDedupe(this: *Lockfile, pkg: *Package, buf: string) OOM!Pack return switch (entry.value_ptr.*) { .id => |existing_id| { - if (pkg.resolution.eql(&resolutions[existing_id], buf, buf)) { - pkg.meta.id = existing_id; - return existing_id; - } - const new_id: PackageID = @intCast(this.packages.len); pkg.meta.id = new_id; try this.packages.append(this.allocator, pkg.*); @@ -2728,13 +2724,6 @@ pub fn appendPackageDedupe(this: *Lockfile, pkg: *Package, buf: string) OOM!Pack return new_id; }, .ids => |*existing_ids| { - for (existing_ids.items) |existing_id| { - if (pkg.resolution.eql(&resolutions[existing_id], buf, buf)) { - pkg.meta.id = existing_id; - return existing_id; - } - } - const new_id: PackageID = @intCast(this.packages.len); pkg.meta.id = new_id; try this.packages.append(this.allocator, pkg.*); @@ -3774,11 +3763,11 @@ pub const Package = extern struct { field: string, behavior: Behavior, - pub const dependencies = DependencyGroup{ .prop = "dependencies", .field = "dependencies", .behavior = Behavior.prod }; - pub const dev = DependencyGroup{ .prop = "devDependencies", .field = "dev_dependencies", .behavior = Behavior.dev }; - pub const optional = DependencyGroup{ .prop = "optionalDependencies", .field = "optional_dependencies", .behavior = Behavior.optional }; - pub const peer = DependencyGroup{ .prop = "peerDependencies", .field = "peer_dependencies", .behavior = Behavior.peer }; - pub const workspaces = DependencyGroup{ .prop = "workspaces", .field = "workspaces", .behavior = Behavior.workspace }; + pub const dependencies = DependencyGroup{ .prop = "dependencies", .field = "dependencies", .behavior = .{ .prod = true } }; + pub const dev = DependencyGroup{ .prop = "devDependencies", .field = "dev_dependencies", .behavior = .{ .dev = true } }; + pub const optional = DependencyGroup{ .prop = "optionalDependencies", .field = "optional_dependencies", .behavior = .{ .optional = true } }; + pub const peer = DependencyGroup{ .prop = "peerDependencies", .field = "peer_dependencies", .behavior = .{ .peer = true } }; + pub const workspaces = DependencyGroup{ .prop = "workspaces", .field = "workspaces", .behavior = .{ .workspace = true } }; }; pub inline fn isDisabled(this: *const Lockfile.Package) bool { @@ -6085,7 +6074,7 @@ pub const Package = extern struct { }; }; - const FieldsEnum = @typeInfo(Lockfile.Package.List.Field).Enum; + const FieldsEnum = @typeInfo(Lockfile.Package.List.Field).@"enum"; pub fn byteSize(list: Lockfile.Package.List) usize { const sizes_vector: std.meta.Vector(sizes.bytes.len, usize) = sizes.bytes; @@ -7512,7 +7501,7 @@ pub fn jsonStringifyDependency(this: *const Lockfile, w: anytype, dep_id: Depend try w.beginObject(); defer w.endObject() catch {}; - const fields = @typeInfo(Behavior).Struct.fields; + const fields = @typeInfo(Behavior).@"struct".fields; inline for (fields[1 .. fields.len - 1]) |field| { if (@field(dep.behavior, field.name)) { try w.objectField(field.name); diff --git a/src/install/migration.zig b/src/install/migration.zig index 71ecc89e8fe7db..fff4faad73baea 100644 --- a/src/install/migration.zig +++ b/src/install/migration.zig @@ -20,7 +20,7 @@ const Npm = @import("./npm.zig"); const Integrity = @import("./integrity.zig").Integrity; const Bin = @import("./bin.zig").Bin; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const String = Semver.String; const ExternalString = Semver.ExternalString; const stringHash = String.Builder.stringHash; @@ -675,7 +675,7 @@ pub fn migrateNPMLockfile( .workspace = wksp_path, }, }, - .behavior = Dependency.Behavior.workspace, + .behavior = .{ .workspace = true }, }; resolutions_buf[0] = entry1.new_package_id; diff --git a/src/install/npm.zig b/src/install/npm.zig index d344de30e5ca5d..de733109d600c0 100644 --- a/src/install/npm.zig +++ b/src/install/npm.zig @@ -2,7 +2,7 @@ const URL = @import("../url.zig").URL; const bun = @import("root").bun; const std = @import("std"); const MutableString = @import("../string_mutable.zig").MutableString; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const String = Semver.String; const string = @import("../string_types.zig").string; @@ -732,7 +732,7 @@ pub const OperatingSystem = enum(u16) { var operating_system = negatable(.none); var iter = args.ptr[0].arrayIterator(globalObject); while (iter.next()) |item| { - const slice = item.toSlice(globalObject, bun.default_allocator); + const slice = try item.toSlice(globalObject, bun.default_allocator); defer slice.deinit(); operating_system.apply(slice.slice()); if (globalObject.hasException()) return .zero; @@ -849,7 +849,7 @@ pub const Architecture = enum(u16) { var architecture = negatable(.none); var iter = args.ptr[0].arrayIterator(globalObject); while (iter.next()) |item| { - const slice = item.toSlice(globalObject, bun.default_allocator); + const slice = try item.toSlice(globalObject, bun.default_allocator); defer slice.deinit(); architecture.apply(slice.slice()); if (globalObject.hasException()) return .zero; diff --git a/src/install/padding_checker.zig b/src/install/padding_checker.zig index fffc6203a90403..597e6da559de4e 100644 --- a/src/install/padding_checker.zig +++ b/src/install/padding_checker.zig @@ -33,17 +33,17 @@ const std = @import("std"); pub fn assertNoUninitializedPadding(comptime T: type) void { const info_ = @typeInfo(T); const info = switch (info_) { - .Struct => info_.Struct, - .Union => info_.Union, - .Array => |a| { + .@"struct" => info_.@"struct", + .@"union" => info_.@"union", + .array => |a| { assertNoUninitializedPadding(a.child); return; }, - .Optional => |a| { + .optional => |a| { assertNoUninitializedPadding(a.child); return; }, - .Pointer => |ptr| { + .pointer => |ptr| { // Pointers aren't allowed, but this just makes the assertion easier to invoke. assertNoUninitializedPadding(ptr.child); return; @@ -58,18 +58,18 @@ pub fn assertNoUninitializedPadding(comptime T: type) void { for (info.fields) |field| { const fieldInfo = @typeInfo(field.type); switch (fieldInfo) { - .Struct => assertNoUninitializedPadding(field.type), - .Union => assertNoUninitializedPadding(field.type), - .Array => |a| assertNoUninitializedPadding(a.child), - .Optional => |a| assertNoUninitializedPadding(a.child), - .Pointer => { + .@"struct" => assertNoUninitializedPadding(field.type), + .@"union" => assertNoUninitializedPadding(field.type), + .array => |a| assertNoUninitializedPadding(a.child), + .optional => |a| assertNoUninitializedPadding(a.child), + .pointer => { @compileError("Expected no pointer types in " ++ @typeName(T) ++ ", found field '" ++ field.name ++ "' of type '" ++ @typeName(field.type) ++ "'"); }, else => {}, } } - if (info_ == .Union) { + if (info_ == .@"union") { return; } diff --git a/src/install/patch_install.zig b/src/install/patch_install.zig index 50e7eb49ecdbd5..a09fce928fa8cb 100644 --- a/src/install/patch_install.zig +++ b/src/install/patch_install.zig @@ -313,7 +313,7 @@ pub const PatchTask = struct { var resolution_buf: [512]u8 = undefined; const resolution_label = std.fmt.bufPrint(&resolution_buf, "{}", .{this.callback.apply.resolution.fmt(strbuf, .posix)}) catch unreachable; - const dummy_node_modules = .{ + const dummy_node_modules: PackageManager.NodeModulesFolder = .{ .path = std.ArrayList(u8).init(this.manager.allocator), .tree_id = 0, }; @@ -335,7 +335,7 @@ pub const PatchTask = struct { switch (pkg_install.installImpl(true, system_tmpdir, .copyfile, this.callback.apply.resolution.tag)) { .success => {}, - .fail => |reason| { + .failure => |reason| { return try log.addErrorFmtOpts( this.manager.allocator, "{s} while executing step: {s}", diff --git a/src/install/repository.zig b/src/install/repository.zig index 8e016bf9656589..3b16f623a5d66b 100644 --- a/src/install/repository.zig +++ b/src/install/repository.zig @@ -8,7 +8,7 @@ const FileSystem = @import("../fs.zig").FileSystem; const Install = @import("./install.zig"); const ExtractData = Install.ExtractData; const PackageManager = Install.PackageManager; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const String = Semver.String; const std = @import("std"); diff --git a/src/install/resolution.zig b/src/install/resolution.zig index d51829b1d40dbd..46d4100874f15d 100644 --- a/src/install/resolution.zig +++ b/src/install/resolution.zig @@ -1,5 +1,5 @@ const PackageManager = @import("./install.zig").PackageManager; -const Semver = @import("./semver.zig"); +const Semver = bun.Semver; const ExternalString = Semver.ExternalString; const String = Semver.String; const std = @import("std"); @@ -20,9 +20,9 @@ pub const Resolution = extern struct { value: Value = .{ .uninitialized = {} }, /// Use like Resolution.init(.{ .npm = VersionedURL{ ... } }) - pub inline fn init(value: anytype) Resolution { + pub inline fn init(value: bun.meta.Tagged(Value, Tag)) Resolution { return Resolution{ - .tag = @field(Tag, @typeInfo(@TypeOf(value)).Struct.fields[0].name), + .tag = std.meta.activeTag(value), .value = Value.init(value), }; } @@ -330,27 +330,30 @@ pub const Resolution = extern struct { npm: VersionedURL, - /// File path to a tarball relative to the package root - local_tarball: String, - folder: String, - /// URL to a tarball. - remote_tarball: String, + /// File path to a tarball relative to the package root + local_tarball: String, - git: Repository, github: Repository, - workspace: String, + git: Repository, /// global link symlink: String, + workspace: String, + + /// URL to a tarball. + remote_tarball: String, + single_file_module: String, /// To avoid undefined memory between union values, we must zero initialize the union first. - pub fn init(field: anytype) Value { - return bun.serializableInto(Value, field); + pub fn init(field: bun.meta.Tagged(Value, Tag)) Value { + return switch (field) { + inline else => |v, t| @unionInit(Value, @tagName(t), v), + }; } }; diff --git a/src/install/resolvers/folder_resolver.zig b/src/install/resolvers/folder_resolver.zig index dceff73f4bccff..287e9a4fc9ad2b 100644 --- a/src/install/resolvers/folder_resolver.zig +++ b/src/install/resolvers/folder_resolver.zig @@ -14,8 +14,8 @@ const Features = @import("../install.zig").Features; const IdentityContext = @import("../../identity_context.zig").IdentityContext; const strings = bun.strings; const Resolution = @import("../resolution.zig").Resolution; -const String = @import("../semver.zig").String; -const Semver = @import("../semver.zig"); +const String = bun.Semver.String; +const Semver = bun.Semver; const bun = @import("root").bun; const Dependency = @import("../dependency.zig"); pub const FolderResolution = union(Tag) { diff --git a/src/install/semver.zig b/src/install/semver.zig deleted file mode 100644 index a3f9ca2efd4cb3..00000000000000 --- a/src/install/semver.zig +++ /dev/null @@ -1,2890 +0,0 @@ -const std = @import("std"); -const Allocator = std.mem.Allocator; -const bun = @import("root").bun; -const string = bun.string; -const Output = bun.Output; -const Global = bun.Global; -const Environment = bun.Environment; -const strings = bun.strings; -const MutableString = bun.MutableString; -const stringZ = bun.stringZ; -const default_allocator = bun.default_allocator; -const C = bun.C; -const JSC = bun.JSC; -const IdentityContext = @import("../identity_context.zig").IdentityContext; -const OOM = bun.OOM; -const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; -const Lockfile = bun.install.Lockfile; - -/// String type that stores either an offset/length into an external buffer or a string inline directly -pub const String = extern struct { - pub const max_inline_len: usize = 8; - /// This is three different types of string. - /// 1. Empty string. If it's all zeroes, then it's an empty string. - /// 2. If the final bit is set, then it's a string that is stored inline. - /// 3. If the final bit is not set, then it's a string that is stored in an external buffer. - bytes: [max_inline_len]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }, - - /// Create an inline string - pub fn from(comptime inlinable_buffer: []const u8) String { - comptime { - if (inlinable_buffer.len > max_inline_len or - inlinable_buffer.len == max_inline_len and - inlinable_buffer[max_inline_len - 1] >= 0x80) - { - @compileError("string constant too long to be inlined"); - } - } - return String.init(inlinable_buffer, inlinable_buffer); - } - - pub const Buf = struct { - bytes: *std.ArrayListUnmanaged(u8), - allocator: std.mem.Allocator, - pool: *Builder.StringPool, - - pub fn init(lockfile: *const Lockfile) Buf { - return .{ - .bytes = &lockfile.buffers.string_bytes, - .allocator = lockfile.allocator, - .pool = &lockfile.string_pool, - }; - } - - pub fn append(this: *Buf, str: string) OOM!String { - if (canInline(str)) { - return String.initInline(str); - } - - const hash = Builder.stringHash(str); - const entry = try this.pool.getOrPut(hash); - if (entry.found_existing) { - return entry.value_ptr.*; - } - - // new entry - const new = try String.initAppend(this.allocator, this.bytes, str); - entry.value_ptr.* = new; - return new; - } - - pub fn appendWithHash(this: *Buf, str: string, hash: u64) OOM!String { - if (canInline(str)) { - return initInline(str); - } - - const entry = try this.pool.getOrPut(hash); - if (entry.found_existing) { - return entry.value_ptr.*; - } - - // new entry - const new = try String.initAppend(this.allocator, this.bytes, str); - entry.value_ptr.* = new; - return new; - } - - pub fn appendExternal(this: *Buf, str: string) OOM!ExternalString { - const hash = Builder.stringHash(str); - - if (canInline(str)) { - return .{ - .value = String.initInline(str), - .hash = hash, - }; - } - - const entry = try this.pool.getOrPut(hash); - if (entry.found_existing) { - return .{ - .value = entry.value_ptr.*, - .hash = hash, - }; - } - - const new = try String.initAppend(this.allocator, this.bytes, str); - entry.value_ptr.* = new; - return .{ - .value = new, - .hash = hash, - }; - } - - pub fn appendExternalWithHash(this: *Buf, str: string, hash: u64) OOM!ExternalString { - if (canInline(str)) { - return .{ - .value = initInline(str), - .hash = hash, - }; - } - - const entry = try this.pool.getOrPut(hash); - if (entry.found_existing) { - return .{ - .value = entry.value_ptr.*, - .hash = hash, - }; - } - - const new = try String.initAppend(this.allocator, this.bytes, str); - entry.value_ptr.* = new; - return .{ - .value = new, - .hash = hash, - }; - } - }; - - pub const Tag = enum { - small, - big, - }; - - pub inline fn fmt(self: *const String, buf: []const u8) Formatter { - return Formatter{ - .buf = buf, - .str = self, - }; - } - - pub const Formatter = struct { - str: *const String, - buf: string, - - pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - const str = formatter.str; - try writer.writeAll(str.slice(formatter.buf)); - } - }; - - /// Escapes for json. Expects string to be prequoted - pub inline fn fmtJson(self: *const String, buf: []const u8, opts: JsonFormatter.Options) JsonFormatter { - return .{ - .buf = buf, - .str = self, - .opts = opts, - }; - } - - pub const JsonFormatter = struct { - str: *const String, - buf: string, - opts: Options, - - pub const Options = struct { - quote: bool = true, - }; - - pub fn format(formatter: JsonFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - try writer.print("{}", .{bun.fmt.formatJSONStringUTF8(formatter.str.slice(formatter.buf), .{ .quote = formatter.opts.quote })}); - } - }; - - pub fn Sorter(comptime direction: enum { asc, desc }) type { - return struct { - lhs_buf: []const u8, - rhs_buf: []const u8, - pub fn lessThan(this: @This(), lhs: String, rhs: String) bool { - return lhs.order(&rhs, this.lhs_buf, this.rhs_buf) == if (comptime direction == .asc) .lt else .gt; - } - }; - } - - pub inline fn order( - lhs: *const String, - rhs: *const String, - lhs_buf: []const u8, - rhs_buf: []const u8, - ) std.math.Order { - return strings.order(lhs.slice(lhs_buf), rhs.slice(rhs_buf)); - } - - pub inline fn canInline(buf: []const u8) bool { - return switch (buf.len) { - 0...max_inline_len - 1 => true, - max_inline_len => buf[max_inline_len - 1] & 0x80 == 0, - else => false, - }; - } - - pub inline fn isInline(this: String) bool { - return this.bytes[max_inline_len - 1] & 0x80 == 0; - } - - pub inline fn sliced(this: *const String, buf: []const u8) SlicedString { - return if (this.isInline()) - SlicedString.init(this.slice(""), this.slice("")) - else - SlicedString.init(buf, this.slice(buf)); - } - - // https://en.wikipedia.org/wiki/Intel_5-level_paging - // https://developer.arm.com/documentation/101811/0101/Address-spaces-in-AArch64#:~:text=0%2DA%2C%20the%20maximum%20size,2%2DA. - // X64 seems to need some of the pointer bits - const max_addressable_space = u63; - - comptime { - if (@sizeOf(usize) != 8) { - @compileError("This code needs to be updated for non-64-bit architectures"); - } - } - - pub const HashContext = struct { - a_buf: []const u8, - b_buf: []const u8, - - pub fn eql(ctx: HashContext, a: String, b: String) bool { - return a.eql(b, ctx.a_buf, ctx.b_buf); - } - - pub fn hash(ctx: HashContext, a: String) u64 { - const str = a.slice(ctx.a_buf); - return bun.hash(str); - } - }; - - pub const ArrayHashContext = struct { - a_buf: []const u8, - b_buf: []const u8, - - pub fn eql(ctx: ArrayHashContext, a: String, b: String, _: usize) bool { - return a.eql(b, ctx.a_buf, ctx.b_buf); - } - - pub fn hash(ctx: ArrayHashContext, a: String) u32 { - const str = a.slice(ctx.a_buf); - return @as(u32, @truncate(bun.hash(str))); - } - }; - - pub fn init( - buf: string, - in: string, - ) String { - return switch (in.len) { - 0 => String{}, - 1 => String{ .bytes = .{ in[0], 0, 0, 0, 0, 0, 0, 0 } }, - 2 => String{ .bytes = .{ in[0], in[1], 0, 0, 0, 0, 0, 0 } }, - 3 => String{ .bytes = .{ in[0], in[1], in[2], 0, 0, 0, 0, 0 } }, - 4 => String{ .bytes = .{ in[0], in[1], in[2], in[3], 0, 0, 0, 0 } }, - 5 => String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], 0, 0, 0 } }, - 6 => String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], 0, 0 } }, - 7 => String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], 0 } }, - max_inline_len => - // If they use the final bit, then it's a big string. - // This should only happen for non-ascii strings that are exactly 8 bytes. - // so that's an edge-case - if ((in[max_inline_len - 1]) >= 128) - @as(String, @bitCast((@as( - u64, - 0, - ) | @as( - u64, - @as( - max_addressable_space, - @truncate(@as( - u64, - @bitCast(Pointer.init(buf, in)), - )), - ), - )) | 1 << 63)) - else - String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] } }, - - else => @as( - String, - @bitCast((@as( - u64, - 0, - ) | @as( - u64, - @as( - max_addressable_space, - @truncate(@as( - u64, - @bitCast(Pointer.init(buf, in)), - )), - ), - )) | 1 << 63), - ), - }; - } - - pub fn initInline( - in: string, - ) String { - bun.assertWithLocation(canInline(in), @src()); - return switch (in.len) { - 0 => .{}, - 1 => .{ .bytes = .{ in[0], 0, 0, 0, 0, 0, 0, 0 } }, - 2 => .{ .bytes = .{ in[0], in[1], 0, 0, 0, 0, 0, 0 } }, - 3 => .{ .bytes = .{ in[0], in[1], in[2], 0, 0, 0, 0, 0 } }, - 4 => .{ .bytes = .{ in[0], in[1], in[2], in[3], 0, 0, 0, 0 } }, - 5 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], 0, 0, 0 } }, - 6 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], 0, 0 } }, - 7 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], 0 } }, - 8 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] } }, - else => unreachable, - }; - } - - pub fn initAppendIfNeeded( - allocator: std.mem.Allocator, - buf: *std.ArrayListUnmanaged(u8), - in: string, - ) OOM!String { - return switch (in.len) { - 0 => .{}, - 1 => .{ .bytes = .{ in[0], 0, 0, 0, 0, 0, 0, 0 } }, - 2 => .{ .bytes = .{ in[0], in[1], 0, 0, 0, 0, 0, 0 } }, - 3 => .{ .bytes = .{ in[0], in[1], in[2], 0, 0, 0, 0, 0 } }, - 4 => .{ .bytes = .{ in[0], in[1], in[2], in[3], 0, 0, 0, 0 } }, - 5 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], 0, 0, 0 } }, - 6 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], 0, 0 } }, - 7 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], 0 } }, - - max_inline_len => - // If they use the final bit, then it's a big string. - // This should only happen for non-ascii strings that are exactly 8 bytes. - // so that's an edge-case - if ((in[max_inline_len - 1]) >= 128) - try initAppend(allocator, buf, in) - else - .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] } }, - - else => try initAppend(allocator, buf, in), - }; - } - - pub fn initAppend( - allocator: std.mem.Allocator, - buf: *std.ArrayListUnmanaged(u8), - in: string, - ) OOM!String { - try buf.appendSlice(allocator, in); - const in_buf = buf.items[buf.items.len - in.len ..]; - return @bitCast((@as(u64, 0) | @as(u64, @as(max_addressable_space, @truncate(@as(u64, @bitCast(Pointer.init(buf.items, in_buf))))))) | 1 << 63); - } - - pub fn eql(this: String, that: String, this_buf: []const u8, that_buf: []const u8) bool { - if (this.isInline() and that.isInline()) { - return @as(u64, @bitCast(this.bytes)) == @as(u64, @bitCast(that.bytes)); - } else if (this.isInline() != that.isInline()) { - return false; - } else { - const a = this.ptr(); - const b = that.ptr(); - return strings.eql(this_buf[a.off..][0..a.len], that_buf[b.off..][0..b.len]); - } - } - - pub inline fn isEmpty(this: String) bool { - return @as(u64, @bitCast(this.bytes)) == @as(u64, 0); - } - - pub fn len(this: String) usize { - switch (this.bytes[max_inline_len - 1] & 128) { - 0 => { - // Edgecase: string that starts with a 0 byte will be considered empty. - switch (this.bytes[0]) { - 0 => { - return 0; - }, - else => { - comptime var i: usize = 0; - - inline while (i < this.bytes.len) : (i += 1) { - if (this.bytes[i] == 0) return i; - } - - return 8; - }, - } - }, - else => { - const ptr_ = this.ptr(); - return ptr_.len; - }, - } - } - - pub const Pointer = extern struct { - off: u32 = 0, - len: u32 = 0, - - pub inline fn init( - buf: string, - in: string, - ) Pointer { - if (Environment.allow_assert) { - assert(bun.isSliceInBuffer(in, buf)); - } - - return Pointer{ - .off = @as(u32, @truncate(@intFromPtr(in.ptr) - @intFromPtr(buf.ptr))), - .len = @as(u32, @truncate(in.len)), - }; - } - }; - - pub inline fn ptr(this: String) Pointer { - return @as(Pointer, @bitCast(@as(u64, @as(u63, @truncate(@as(u64, @bitCast(this))))))); - } - - pub fn toJS(this: *const String, buffer: []const u8, globalThis: *JSC.JSGlobalObject) JSC.JSValue { - var str = bun.String.init(this.slice(buffer)); - return str.transferToJS(globalThis); - } - - // String must be a pointer because we reference it as a slice. It will become a dead pointer if it is copied. - pub fn slice(this: *const String, buf: string) string { - switch (this.bytes[max_inline_len - 1] & 128) { - 0 => { - // Edgecase: string that starts with a 0 byte will be considered empty. - switch (this.bytes[0]) { - 0 => { - return ""; - }, - else => { - comptime var i: usize = 0; - - inline while (i < this.bytes.len) : (i += 1) { - if (this.bytes[i] == 0) return this.bytes[0..i]; - } - - return &this.bytes; - }, - } - }, - else => { - const ptr_ = this.*.ptr(); - return buf[ptr_.off..][0..ptr_.len]; - }, - } - } - - pub const Builder = struct { - len: usize = 0, - cap: usize = 0, - ptr: ?[*]u8 = null, - string_pool: StringPool = undefined, - - pub const StringPool = std.HashMap(u64, String, IdentityContext(u64), 80); - - pub inline fn stringHash(buf: []const u8) u64 { - return bun.Wyhash11.hash(0, buf); - } - - pub inline fn count(this: *Builder, slice_: string) void { - return countWithHash(this, slice_, if (slice_.len >= String.max_inline_len) stringHash(slice_) else std.math.maxInt(u64)); - } - - pub inline fn countWithHash(this: *Builder, slice_: string, hash: u64) void { - if (slice_.len <= String.max_inline_len) return; - - if (!this.string_pool.contains(hash)) { - this.cap += slice_.len; - } - } - - pub inline fn allocatedSlice(this: *Builder) []u8 { - return if (this.cap > 0) - this.ptr.?[0..this.cap] - else - &[_]u8{}; - } - pub fn allocate(this: *Builder, allocator: Allocator) !void { - const ptr_ = try allocator.alloc(u8, this.cap); - this.ptr = ptr_.ptr; - } - - pub fn append(this: *Builder, comptime Type: type, slice_: string) Type { - return @call(bun.callmod_inline, appendWithHash, .{ this, Type, slice_, stringHash(slice_) }); - } - - pub fn appendUTF8WithoutPool(this: *Builder, comptime Type: type, slice_: string, hash: u64) Type { - if (slice_.len <= String.max_inline_len) { - if (strings.isAllASCII(slice_)) { - switch (Type) { - String => { - return String.init(this.allocatedSlice(), slice_); - }, - ExternalString => { - return ExternalString.init(this.allocatedSlice(), slice_, hash); - }, - else => @compileError("Invalid type passed to StringBuilder"), - } - } - } - - if (comptime Environment.allow_assert) { - assert(this.len <= this.cap); // didn't count everything - assert(this.ptr != null); // must call allocate first - } - - bun.copy(u8, this.ptr.?[this.len..this.cap], slice_); - const final_slice = this.ptr.?[this.len..this.cap][0..slice_.len]; - this.len += slice_.len; - - if (comptime Environment.allow_assert) assert(this.len <= this.cap); - - switch (Type) { - String => { - return String.init(this.allocatedSlice(), final_slice); - }, - ExternalString => { - return ExternalString.init(this.allocatedSlice(), final_slice, hash); - }, - else => @compileError("Invalid type passed to StringBuilder"), - } - } - - // SlicedString is not supported due to inline strings. - pub fn appendWithoutPool(this: *Builder, comptime Type: type, slice_: string, hash: u64) Type { - if (slice_.len <= String.max_inline_len) { - switch (Type) { - String => { - return String.init(this.allocatedSlice(), slice_); - }, - ExternalString => { - return ExternalString.init(this.allocatedSlice(), slice_, hash); - }, - else => @compileError("Invalid type passed to StringBuilder"), - } - } - if (comptime Environment.allow_assert) { - assert(this.len <= this.cap); // didn't count everything - assert(this.ptr != null); // must call allocate first - } - - bun.copy(u8, this.ptr.?[this.len..this.cap], slice_); - const final_slice = this.ptr.?[this.len..this.cap][0..slice_.len]; - this.len += slice_.len; - - if (comptime Environment.allow_assert) assert(this.len <= this.cap); - - switch (Type) { - String => { - return String.init(this.allocatedSlice(), final_slice); - }, - ExternalString => { - return ExternalString.init(this.allocatedSlice(), final_slice, hash); - }, - else => @compileError("Invalid type passed to StringBuilder"), - } - } - - pub fn appendWithHash(this: *Builder, comptime Type: type, slice_: string, hash: u64) Type { - if (slice_.len <= String.max_inline_len) { - switch (Type) { - String => { - return String.init(this.allocatedSlice(), slice_); - }, - ExternalString => { - return ExternalString.init(this.allocatedSlice(), slice_, hash); - }, - else => @compileError("Invalid type passed to StringBuilder"), - } - } - - if (comptime Environment.allow_assert) { - assert(this.len <= this.cap); // didn't count everything - assert(this.ptr != null); // must call allocate first - } - - const string_entry = this.string_pool.getOrPut(hash) catch unreachable; - if (!string_entry.found_existing) { - bun.copy(u8, this.ptr.?[this.len..this.cap], slice_); - const final_slice = this.ptr.?[this.len..this.cap][0..slice_.len]; - this.len += slice_.len; - - string_entry.value_ptr.* = String.init(this.allocatedSlice(), final_slice); - } - - if (comptime Environment.allow_assert) assert(this.len <= this.cap); - - switch (Type) { - String => { - return string_entry.value_ptr.*; - }, - ExternalString => { - return ExternalString{ - .value = string_entry.value_ptr.*, - .hash = hash, - }; - }, - else => @compileError("Invalid type passed to StringBuilder"), - } - } - }; - - comptime { - if (@sizeOf(String) != @sizeOf(Pointer)) { - @compileError("String types must be the same size"); - } - } -}; - -test "String works" { - { - var buf: string = "hello world"; - const world: string = buf[6..]; - var str = String.init( - buf, - world, - ); - try std.testing.expectEqualStrings("world", str.slice(buf)); - } - - { - const buf: string = "hello"; - const world: string = buf; - var str = String.init( - buf, - world, - ); - try std.testing.expectEqualStrings("hello", str.slice(buf)); - try std.testing.expectEqual(@as(u64, @bitCast(str)), @as(u64, @bitCast([8]u8{ 'h', 'e', 'l', 'l', 'o', 0, 0, 0 }))); - } - - { - const buf: string = &[8]u8{ 'h', 'e', 'l', 'l', 'o', 'k', 'k', 129 }; - const world: string = buf; - var str = String.init( - buf, - world, - ); - try std.testing.expectEqualStrings(buf, str.slice(buf)); - } -} - -pub const ExternalString = extern struct { - value: String = String{}, - hash: u64 = 0, - - pub inline fn fmt(this: *const ExternalString, buf: []const u8) String.Formatter { - return this.value.fmt(buf); - } - - pub fn order(lhs: *const ExternalString, rhs: *const ExternalString, lhs_buf: []const u8, rhs_buf: []const u8) std.math.Order { - if (lhs.hash == rhs.hash and lhs.hash > 0) return .eq; - - return lhs.value.order(&rhs.value, lhs_buf, rhs_buf); - } - - /// ExternalString but without the hash - pub inline fn from(in: string) ExternalString { - return ExternalString{ - .value = String.init(in, in), - .hash = bun.Wyhash.hash(0, in), - }; - } - - pub inline fn isInline(this: ExternalString) bool { - return this.value.isInline(); - } - - pub inline fn isEmpty(this: ExternalString) bool { - return this.value.isEmpty(); - } - - pub inline fn len(this: ExternalString) usize { - return this.value.len(); - } - - pub inline fn init(buf: string, in: string, hash: u64) ExternalString { - return ExternalString{ - .value = String.init(buf, in), - .hash = hash, - }; - } - - pub inline fn slice(this: *const ExternalString, buf: string) string { - return this.value.slice(buf); - } -}; - -pub const SlicedString = struct { - buf: string, - slice: string, - - pub inline fn init(buf: string, slice: string) SlicedString { - if (Environment.allow_assert and !@inComptime()) { - if (@intFromPtr(buf.ptr) > @intFromPtr(slice.ptr)) { - @panic("SlicedString.init buf is not in front of slice"); - } - } - return SlicedString{ .buf = buf, .slice = slice }; - } - - pub inline fn external(this: SlicedString) ExternalString { - if (comptime Environment.allow_assert) { - assert(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.slice.ptr) and ((@intFromPtr(this.slice.ptr) + this.slice.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len))); - } - - return ExternalString.init(this.buf, this.slice, bun.Wyhash11.hash(0, this.slice)); - } - - pub inline fn value(this: SlicedString) String { - if (comptime Environment.allow_assert) { - assert(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.slice.ptr) and ((@intFromPtr(this.slice.ptr) + this.slice.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len))); - } - - return String.init(this.buf, this.slice); - } - - pub inline fn sub(this: SlicedString, input: string) SlicedString { - if (Environment.allow_assert) { - if (!(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.buf.ptr) and ((@intFromPtr(input.ptr) + input.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len)))) { - @panic("SlicedString.sub input is not a substring of the slice"); - } - } - return SlicedString{ .buf = this.buf, .slice = input }; - } -}; - -pub const Version = extern struct { - major: u32 = 0, - minor: u32 = 0, - patch: u32 = 0, - _tag_padding: [4]u8 = .{0} ** 4, // [see padding_checker.zig] - tag: Tag = .{}, - - /// Assumes that there is only one buffer for all the strings - pub fn sortGt(ctx: []const u8, lhs: Version, rhs: Version) bool { - return orderFn(ctx, lhs, rhs) == .gt; - } - - pub fn orderFn(ctx: []const u8, lhs: Version, rhs: Version) std.math.Order { - return lhs.order(rhs, ctx, ctx); - } - - pub fn isZero(this: Version) bool { - return this.patch == 0 and this.minor == 0 and this.major == 0; - } - - pub fn parseUTF8(slice: []const u8) ParseResult { - return parse(.{ .buf = slice, .slice = slice }); - } - - pub fn cloneInto(this: Version, slice: []const u8, buf: *[]u8) Version { - return .{ - .major = this.major, - .minor = this.minor, - .patch = this.patch, - .tag = this.tag.cloneInto(slice, buf), - }; - } - - pub inline fn len(this: *const Version) u32 { - return this.tag.build.len + this.tag.pre.len; - } - - pub const Formatter = struct { - version: Version, - input: string, - - pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - const self = formatter.version; - try std.fmt.format(writer, "{?d}.{?d}.{?d}", .{ self.major, self.minor, self.patch }); - - if (self.tag.hasPre()) { - const pre = self.tag.pre.slice(formatter.input); - try writer.writeAll("-"); - try writer.writeAll(pre); - } - - if (self.tag.hasBuild()) { - const build = self.tag.build.slice(formatter.input); - try writer.writeAll("+"); - try writer.writeAll(build); - } - } - }; - - pub fn fmt(this: Version, input: string) Formatter { - return .{ .version = this, .input = input }; - } - - pub const DiffFormatter = struct { - version: Version, - buf: string, - other: Version, - other_buf: string, - - pub fn format(this: DiffFormatter, comptime fmt_: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { - if (!Output.enable_ansi_colors) { - // print normally if no colors - const formatter: Formatter = .{ .version = this.version, .input = this.buf }; - return Formatter.format(formatter, fmt_, options, writer); - } - - const diff = this.version.whichVersionIsDifferent(this.other, this.buf, this.other_buf) orelse .none; - - switch (diff) { - .major => try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ - this.version.major, this.version.minor, this.version.patch, - }), - .minor => { - if (this.version.major == 0) { - try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ - this.version.major, this.version.minor, this.version.patch, - }); - } else { - try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ - this.version.major, this.version.minor, this.version.patch, - }); - } - }, - .patch => { - if (this.version.major == 0 and this.version.minor == 0) { - try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ - this.version.major, this.version.minor, this.version.patch, - }); - } else { - try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ - this.version.major, this.version.minor, this.version.patch, - }); - } - }, - .none, .pre, .build => try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ - this.version.major, this.version.minor, this.version.patch, - }), - } - - // might be pre or build. loop through all characters, and insert on - // first diff. - - var set_color = false; - if (this.version.tag.hasPre()) { - if (this.other.tag.hasPre()) { - const pre = this.version.tag.pre.slice(this.buf); - const other_pre = this.other.tag.pre.slice(this.other_buf); - - var first = true; - for (pre, 0..) |c, i| { - if (!set_color and i < other_pre.len and c != other_pre[i]) { - set_color = true; - try writer.writeAll(Output.prettyFmt("", true)); - } - if (first) { - first = false; - try writer.writeByte('-'); - } - try writer.writeByte(c); - } - } else { - try writer.print(Output.prettyFmt("-{}", true), .{this.version.tag.pre.fmt(this.buf)}); - set_color = true; - } - } - - if (this.version.tag.hasBuild()) { - if (this.other.tag.hasBuild()) { - const build = this.version.tag.build.slice(this.buf); - const other_build = this.other.tag.build.slice(this.other_buf); - - var first = true; - for (build, 0..) |c, i| { - if (!set_color and i < other_build.len and c != other_build[i]) { - set_color = true; - try writer.writeAll(Output.prettyFmt("", true)); - } - if (first) { - first = false; - try writer.writeByte('+'); - } - try writer.writeByte(c); - } - } else { - if (!set_color) { - try writer.print(Output.prettyFmt("+{}", true), .{this.version.tag.build.fmt(this.buf)}); - } else { - try writer.print("+{}", .{this.version.tag.build.fmt(this.other_buf)}); - } - } - } - - try writer.writeAll(Output.prettyFmt("", true)); - } - }; - - pub fn diffFmt(this: Version, other: Version, this_buf: string, other_buf: string) DiffFormatter { - return .{ - .version = this, - .buf = this_buf, - .other = other, - .other_buf = other_buf, - }; - } - - pub const ChangedVersion = enum { - major, - minor, - patch, - pre, - build, - none, - }; - - pub fn whichVersionIsDifferent( - left: Version, - right: Version, - left_buf: string, - right_buf: string, - ) ?ChangedVersion { - if (left.major != right.major) return .major; - if (left.minor != right.minor) return .minor; - if (left.patch != right.patch) return .patch; - - if (left.tag.hasPre() != right.tag.hasPre()) return .pre; - if (!left.tag.hasPre() and !right.tag.hasPre()) return null; - if (left.tag.orderPre(right.tag, left_buf, right_buf) != .eq) return .pre; - - if (left.tag.hasBuild() != right.tag.hasBuild()) return .build; - if (!left.tag.hasBuild() and !right.tag.hasBuild()) return null; - return if (left.tag.build.order(&right.tag.build, left_buf, right_buf) != .eq) - .build - else - null; - } - - pub fn count(this: *const Version, buf: []const u8, comptime StringBuilder: type, builder: StringBuilder) void { - if (this.tag.hasPre() and !this.tag.pre.isInline()) builder.count(this.tag.pre.slice(buf)); - if (this.tag.hasBuild() and !this.tag.build.isInline()) builder.count(this.tag.build.slice(buf)); - } - - pub fn append(this: *const Version, buf: []const u8, comptime StringBuilder: type, builder: StringBuilder) Version { - var that = this.*; - - if (this.tag.hasPre() and !this.tag.pre.isInline()) that.tag.pre = builder.append(ExternalString, this.tag.pre.slice(buf)); - if (this.tag.hasBuild() and !this.tag.build.isInline()) that.tag.build = builder.append(ExternalString, this.tag.build.slice(buf)); - - return that; - } - - pub const Partial = struct { - major: ?u32 = null, - minor: ?u32 = null, - patch: ?u32 = null, - tag: Tag = .{}, - - pub fn min(this: Partial) Version { - return .{ - .major = this.major orelse 0, - .minor = this.minor orelse 0, - .patch = this.patch orelse 0, - .tag = this.tag, - }; - } - - pub fn max(this: Partial) Version { - return .{ - .major = this.major orelse std.math.maxInt(u32), - .minor = this.minor orelse std.math.maxInt(u32), - .patch = this.patch orelse std.math.maxInt(u32), - .tag = this.tag, - }; - } - }; - - const Hashable = extern struct { - major: u32, - minor: u32, - patch: u32, - pre: u64, - build: u64, - }; - - pub fn hash(this: Version) u64 { - const hashable = Hashable{ - .major = this.major, - .minor = this.minor, - .patch = this.patch, - .pre = this.tag.pre.hash, - .build = this.tag.build.hash, - }; - const bytes = std.mem.asBytes(&hashable); - return bun.Wyhash.hash(0, bytes); - } - - pub fn eql(lhs: Version, rhs: Version) bool { - return lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch and rhs.tag.eql(lhs.tag); - } - - pub const HashContext = struct { - pub fn hash(_: @This(), lhs: Version) u32 { - return @as(u32, @truncate(lhs.hash())); - } - - pub fn eql(_: @This(), lhs: Version, rhs: Version) bool { - return lhs.eql(rhs); - } - }; - - pub const PinnedVersion = enum { - major, // ^ - minor, // ~ - patch, // = - }; - - /// Modified version of pnpm's `whichVersionIsPinned` - /// https://github.com/pnpm/pnpm/blob/bc0618cf192a9cafd0ab171a3673e23ed0869bbd/packages/which-version-is-pinned/src/index.ts#L9 - /// - /// Differences: - /// - It's not used for workspaces - /// - `npm:` is assumed already removed from aliased versions - /// - Invalid input is considered major pinned (important because these strings are coming - /// from package.json) - /// - /// The goal of this function is to avoid a complete parse of semver that's unused - pub fn whichVersionIsPinned(input: string) PinnedVersion { - const version = strings.trim(input, &strings.whitespace_chars); - - var i: usize = 0; - - const pinned: PinnedVersion = pinned: { - for (0..version.len) |j| { - switch (version[j]) { - // newlines & whitespace - ' ', - '\t', - '\n', - '\r', - std.ascii.control_code.vt, - std.ascii.control_code.ff, - - // version separators - 'v', - '=', - => {}, - - else => |c| { - i = j; - - switch (c) { - '~', '^' => { - i += 1; - - for (i..version.len) |k| { - switch (version[k]) { - ' ', - '\t', - '\n', - '\r', - std.ascii.control_code.vt, - std.ascii.control_code.ff, - => { - // `v` and `=` not included. - // `~v==1` would update to `^1.1.0` if versions `1.0.0`, `1.0.1`, `1.1.0`, and `2.0.0` are available - // note that `~` changes to `^` - }, - - else => { - i = k; - break :pinned if (c == '~') .minor else .major; - }, - } - } - - // entire version after `~` is whitespace. invalid - return .major; - }, - - '0'...'9' => break :pinned .patch, - - // could be invalid, could also be valid range syntax (>=, ...) - // either way, pin major - else => return .major, - } - }, - } - } - - // entire semver is whitespace, `v`, and `=`. Invalid - return .major; - }; - - // `pinned` is `.major`, `.minor`, or `.patch`. Check for each version core number: - // - if major is missing, return `if (pinned == .patch) .major else pinned` - // - if minor is missing, return `if (pinned == .patch) .minor else pinned` - // - if patch is missing, return `pinned` - // - if there's whitespace or non-digit characters between core numbers, return `.major` - // - if the end is reached, return `pinned` - - // major - if (i >= version.len or !std.ascii.isDigit(version[i])) return .major; - var d = version[i]; - while (std.ascii.isDigit(d)) { - i += 1; - if (i >= version.len) return if (pinned == .patch) .major else pinned; - d = version[i]; - } - - if (d != '.') return .major; - - // minor - i += 1; - if (i >= version.len or !std.ascii.isDigit(version[i])) return .major; - d = version[i]; - while (std.ascii.isDigit(d)) { - i += 1; - if (i >= version.len) return if (pinned == .patch) .minor else pinned; - d = version[i]; - } - - if (d != '.') return .major; - - // patch - i += 1; - if (i >= version.len or !std.ascii.isDigit(version[i])) return .major; - d = version[i]; - while (std.ascii.isDigit(d)) { - i += 1; - - // patch is done and at input end, valid - if (i >= version.len) return pinned; - d = version[i]; - } - - // Skip remaining valid pre/build tag characters and whitespace. - // Does not validate whitespace used inside pre/build tags. - if (!validPreOrBuildTagCharacter(d) or std.ascii.isWhitespace(d)) return .major; - i += 1; - - // at this point the semver is valid so we can return true if it ends - if (i >= version.len) return pinned; - d = version[i]; - while (validPreOrBuildTagCharacter(d) and !std.ascii.isWhitespace(d)) { - i += 1; - if (i >= version.len) return pinned; - d = version[i]; - } - - // We've come across a character that is not valid for tags or is whitespace. - // Trailing whitespace was trimmed so we can assume there's another range - return .major; - } - - fn validPreOrBuildTagCharacter(c: u8) bool { - return switch (c) { - '-', '+', '.', 'A'...'Z', 'a'...'z', '0'...'9' => true, - else => false, - }; - } - - pub fn isTaggedVersionOnly(input: []const u8) bool { - const version = strings.trim(input, &strings.whitespace_chars); - - // first needs to be a-z - if (version.len == 0 or !std.ascii.isAlphabetic(version[0])) return false; - - for (1..version.len) |i| { - if (!std.ascii.isAlphanumeric(version[i])) return false; - } - - return true; - } - - pub fn orderWithoutTag( - lhs: Version, - rhs: Version, - ) std.math.Order { - if (lhs.major < rhs.major) return .lt; - if (lhs.major > rhs.major) return .gt; - if (lhs.minor < rhs.minor) return .lt; - if (lhs.minor > rhs.minor) return .gt; - if (lhs.patch < rhs.patch) return .lt; - if (lhs.patch > rhs.patch) return .gt; - - if (lhs.tag.hasPre()) { - if (!rhs.tag.hasPre()) return .lt; - } else { - if (rhs.tag.hasPre()) return .gt; - } - - return .eq; - } - - pub fn order( - lhs: Version, - rhs: Version, - lhs_buf: []const u8, - rhs_buf: []const u8, - ) std.math.Order { - const order_without_tag = orderWithoutTag(lhs, rhs); - if (order_without_tag != .eq) return order_without_tag; - - return lhs.tag.order(rhs.tag, lhs_buf, rhs_buf); - } - - pub fn orderWithoutBuild( - lhs: Version, - rhs: Version, - lhs_buf: []const u8, - rhs_buf: []const u8, - ) std.math.Order { - const order_without_tag = orderWithoutTag(lhs, rhs); - if (order_without_tag != .eq) return order_without_tag; - - return lhs.tag.orderWithoutBuild(rhs.tag, lhs_buf, rhs_buf); - } - - pub const Tag = extern struct { - pre: ExternalString = ExternalString{}, - build: ExternalString = ExternalString{}, - - pub fn orderPre(lhs: Tag, rhs: Tag, lhs_buf: []const u8, rhs_buf: []const u8) std.math.Order { - const lhs_str = lhs.pre.slice(lhs_buf); - const rhs_str = rhs.pre.slice(rhs_buf); - - // 1. split each by '.', iterating through each one looking for integers - // 2. compare as integers, or if not possible compare as string - // 3. whichever is greater is the greater one - // - // 1.0.0-canary.0.0.0.0.0.0 < 1.0.0-canary.0.0.0.0.0.1 - - var lhs_itr = strings.split(lhs_str, "."); - var rhs_itr = strings.split(rhs_str, "."); - - while (true) { - const lhs_part = lhs_itr.next(); - const rhs_part = rhs_itr.next(); - - if (lhs_part == null and rhs_part == null) return .eq; - - // if right is null, left is greater than. - if (rhs_part == null) return .gt; - - // if left is null, left is less than. - if (lhs_part == null) return .lt; - - const lhs_uint: ?u32 = std.fmt.parseUnsigned(u32, lhs_part.?, 10) catch null; - const rhs_uint: ?u32 = std.fmt.parseUnsigned(u32, rhs_part.?, 10) catch null; - - // a part that doesn't parse as an integer is greater than a part that does - // https://github.com/npm/node-semver/blob/816c7b2cbfcb1986958a290f941eddfd0441139e/internal/identifiers.js#L12 - if (lhs_uint != null and rhs_uint == null) return .lt; - if (lhs_uint == null and rhs_uint != null) return .gt; - - if (lhs_uint == null and rhs_uint == null) { - switch (strings.order(lhs_part.?, rhs_part.?)) { - .eq => { - // continue to the next part - continue; - }, - else => |not_equal| return not_equal, - } - } - - switch (std.math.order(lhs_uint.?, rhs_uint.?)) { - .eq => continue, - else => |not_equal| return not_equal, - } - } - - unreachable; - } - - pub fn order( - lhs: Tag, - rhs: Tag, - lhs_buf: []const u8, - rhs_buf: []const u8, - ) std.math.Order { - if (!lhs.pre.isEmpty() and !rhs.pre.isEmpty()) { - return lhs.orderPre(rhs, lhs_buf, rhs_buf); - } - - const pre_order = lhs.pre.order(&rhs.pre, lhs_buf, rhs_buf); - if (pre_order != .eq) return pre_order; - - return lhs.build.order(&rhs.build, lhs_buf, rhs_buf); - } - - pub fn orderWithoutBuild( - lhs: Tag, - rhs: Tag, - lhs_buf: []const u8, - rhs_buf: []const u8, - ) std.math.Order { - if (!lhs.pre.isEmpty() and !rhs.pre.isEmpty()) { - return lhs.orderPre(rhs, lhs_buf, rhs_buf); - } - - return lhs.pre.order(&rhs.pre, lhs_buf, rhs_buf); - } - - pub fn cloneInto(this: Tag, slice: []const u8, buf: *[]u8) Tag { - var pre: String = this.pre.value; - var build: String = this.build.value; - - if (this.pre.isInline()) { - pre = this.pre.value; - } else { - const pre_slice = this.pre.slice(slice); - bun.copy(u8, buf.*, pre_slice); - pre = String.init(buf.*, buf.*[0..pre_slice.len]); - buf.* = buf.*[pre_slice.len..]; - } - - if (this.build.isInline()) { - build = this.build.value; - } else { - const build_slice = this.build.slice(slice); - bun.copy(u8, buf.*, build_slice); - build = String.init(buf.*, buf.*[0..build_slice.len]); - buf.* = buf.*[build_slice.len..]; - } - - return .{ - .pre = .{ - .value = pre, - .hash = this.pre.hash, - }, - .build = .{ - .value = build, - .hash = this.build.hash, - }, - }; - } - - pub inline fn hasPre(this: Tag) bool { - return !this.pre.isEmpty(); - } - - pub inline fn hasBuild(this: Tag) bool { - return !this.build.isEmpty(); - } - - pub fn eql(lhs: Tag, rhs: Tag) bool { - return lhs.pre.hash == rhs.pre.hash; - } - - pub const TagResult = struct { - tag: Tag = Tag{}, - len: u32 = 0, - }; - - var multi_tag_warn = false; - // TODO: support multiple tags - - pub fn parse(sliced_string: SlicedString) TagResult { - return parseWithPreCount(sliced_string, 0); - } - - pub fn parseWithPreCount(sliced_string: SlicedString, initial_pre_count: u32) TagResult { - var input = sliced_string.slice; - var build_count: u32 = 0; - var pre_count: u32 = initial_pre_count; - - for (input) |c| { - switch (c) { - ' ' => break, - '+' => { - build_count += 1; - }, - '-' => { - pre_count += 1; - }, - else => {}, - } - } - - if (build_count == 0 and pre_count == 0) { - return TagResult{ - .len = 0, - }; - } - - const State = enum { none, pre, build }; - var result = TagResult{}; - // Common case: no allocation is necessary. - var state = State.none; - var start: usize = 0; - - var i: usize = 0; - - while (i < input.len) : (i += 1) { - const c = input[i]; - switch (c) { - '+' => { - // qualifier ::= ( '-' pre )? ( '+' build )? - if (state == .pre or state == .none and initial_pre_count > 0) { - result.tag.pre = sliced_string.sub(input[start..i]).external(); - } - - if (state != .build) { - state = .build; - start = i + 1; - } - }, - '-' => { - if (state != .pre) { - state = .pre; - start = i + 1; - } - }, - - // only continue if character is a valid pre/build tag character - // https://semver.org/#spec-item-9 - 'a'...'z', 'A'...'Z', '0'...'9', '.' => {}, - - else => { - switch (state) { - .none => {}, - .pre => { - result.tag.pre = sliced_string.sub(input[start..i]).external(); - - state = State.none; - }, - .build => { - result.tag.build = sliced_string.sub(input[start..i]).external(); - if (comptime Environment.isDebug) { - assert(!strings.containsChar(result.tag.build.slice(sliced_string.buf), '-')); - } - state = State.none; - }, - } - result.len = @truncate(i); - break; - }, - } - } - - if (state == .none and initial_pre_count > 0) { - state = .pre; - start = 0; - } - - switch (state) { - .none => {}, - .pre => { - result.tag.pre = sliced_string.sub(input[start..i]).external(); - // a pre can contain multiple consecutive tags - // checking for "-" prefix is not enough, as --canary.67e7966.0 is a valid tag - state = State.none; - }, - .build => { - // a build can contain multiple consecutive tags - result.tag.build = sliced_string.sub(input[start..i]).external(); - - state = State.none; - }, - } - result.len = @as(u32, @truncate(i)); - - return result; - } - }; - - pub const ParseResult = struct { - wildcard: Query.Token.Wildcard = .none, - valid: bool = true, - version: Version.Partial = .{}, - len: u32 = 0, - }; - - pub fn parse(sliced_string: SlicedString) ParseResult { - var input = sliced_string.slice; - var result = ParseResult{}; - - var part_i: u8 = 0; - var part_start_i: usize = 0; - var last_char_i: usize = 0; - - if (input.len == 0) { - result.valid = false; - return result; - } - var is_done = false; - - var i: usize = 0; - - for (0..input.len) |c| { - switch (input[c]) { - // newlines & whitespace - ' ', - '\t', - '\n', - '\r', - std.ascii.control_code.vt, - std.ascii.control_code.ff, - - // version separators - 'v', - '=', - => {}, - else => { - i = c; - break; - }, - } - } - - if (i == input.len) { - result.valid = false; - return result; - } - - // two passes :( - while (i < input.len) { - if (is_done) { - break; - } - - switch (input[i]) { - ' ' => { - is_done = true; - break; - }, - '|', '^', '#', '&', '%', '!' => { - is_done = true; - if (i > 0) { - i -= 1; - } - break; - }, - '0'...'9' => { - part_start_i = i; - i += 1; - - while (i < input.len and switch (input[i]) { - '0'...'9' => true, - else => false, - }) { - i += 1; - } - - last_char_i = i; - - switch (part_i) { - 0 => { - result.version.major = parseVersionNumber(input[part_start_i..last_char_i]); - part_i = 1; - }, - 1 => { - result.version.minor = parseVersionNumber(input[part_start_i..last_char_i]); - part_i = 2; - }, - 2 => { - result.version.patch = parseVersionNumber(input[part_start_i..last_char_i]); - part_i = 3; - }, - else => {}, - } - - if (i < input.len and switch (input[i]) { - // `.` is expected only if there are remaining core version numbers - '.' => part_i != 3, - else => false, - }) { - i += 1; - } - }, - '.' => { - result.valid = false; - is_done = true; - break; - }, - '-', '+' => { - // Just a plain tag with no version is invalid. - if (part_i < 2 and result.wildcard == .none) { - result.valid = false; - is_done = true; - break; - } - - part_start_i = i; - while (i < input.len and switch (input[i]) { - ' ' => true, - else => false, - }) { - i += 1; - } - const tag_result = Tag.parse(sliced_string.sub(input[part_start_i..])); - result.version.tag = tag_result.tag; - i += tag_result.len; - break; - }, - 'x', '*', 'X' => { - part_start_i = i; - i += 1; - - while (i < input.len and switch (input[i]) { - 'x', '*', 'X' => true, - else => false, - }) { - i += 1; - } - - last_char_i = i; - - if (i < input.len and switch (input[i]) { - '.' => true, - else => false, - }) { - i += 1; - } - - if (result.wildcard == .none) { - switch (part_i) { - 0 => { - result.wildcard = Query.Token.Wildcard.major; - part_i = 1; - }, - 1 => { - result.wildcard = Query.Token.Wildcard.minor; - part_i = 2; - }, - 2 => { - result.wildcard = Query.Token.Wildcard.patch; - part_i = 3; - }, - else => unreachable, - } - } - }, - else => |c| { - - // Some weirdo npm packages in the wild have a version like "1.0.0rc.1" - // npm just expects that to work...even though it has no "-" qualifier. - if (result.wildcard == .none and part_i >= 2 and switch (c) { - 'a'...'z', 'A'...'Z' => true, - else => false, - }) { - part_start_i = i; - const tag_result = Tag.parseWithPreCount(sliced_string.sub(input[part_start_i..]), 1); - result.version.tag = tag_result.tag; - i += tag_result.len; - is_done = true; - last_char_i = i; - break; - } - - last_char_i = 0; - result.valid = false; - is_done = true; - break; - }, - } - } - - if (result.wildcard == .none) { - switch (part_i) { - 0 => { - result.wildcard = Query.Token.Wildcard.major; - }, - 1 => { - result.wildcard = Query.Token.Wildcard.minor; - }, - 2 => { - result.wildcard = Query.Token.Wildcard.patch; - }, - else => {}, - } - } - - result.len = @as(u32, @intCast(i)); - - return result; - } - - fn parseVersionNumber(input: string) ?u32 { - // max decimal u32 is 4294967295 - var bytes: [10]u8 = undefined; - var byte_i: u8 = 0; - - assert(input[0] != '.'); - - for (input) |char| { - switch (char) { - 'X', 'x', '*' => return null, - '0'...'9' => { - // out of bounds - if (byte_i + 1 > bytes.len) return null; - bytes[byte_i] = char; - byte_i += 1; - }, - ' ', '.' => break, - // ignore invalid characters - else => {}, - } - } - - // If there are no numbers - if (byte_i == 0) return null; - - if (comptime Environment.isDebug) { - return std.fmt.parseInt(u32, bytes[0..byte_i], 10) catch |err| { - Output.prettyErrorln("ERROR {s} parsing version: \"{s}\", bytes: {s}", .{ - @errorName(err), - input, - bytes[0..byte_i], - }); - return 0; - }; - } - - return std.fmt.parseInt(u32, bytes[0..byte_i], 10) catch 0; - } -}; - -pub const Range = struct { - pub const Op = enum(u8) { - unset = 0, - eql = 1, - lt = 3, - lte = 4, - gt = 5, - gte = 6, - }; - - left: Comparator = .{}, - right: Comparator = .{}, - - pub fn format(this: Range, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - if (this.left.op == .unset and this.right.op == .unset) { - return; - } - - if (this.right.op == .unset) { - try std.fmt.format(writer, "{}", .{this.left}); - } else { - try std.fmt.format(writer, "{} {}", .{ this.left, this.right }); - } - } - - /// * - /// >= 0.0.0 - /// >= 0 - /// >= 0.0 - /// >= x - /// >= 0 - pub fn anyRangeSatisfies(this: *const Range) bool { - return this.left.op == .gte and this.left.version.eql(.{}); - } - - pub fn initWildcard(version: Version, wildcard: Query.Token.Wildcard) Range { - switch (wildcard) { - .none => { - return .{ - .left = .{ - .op = Op.eql, - .version = version, - }, - }; - }, - - .major => { - return .{ - .left = .{ - .op = Op.gte, - .version = .{ - // .raw = version.raw - }, - }, - }; - }, - .minor => { - const lhs = Version{ - .major = version.major +| 1, - // .raw = version.raw - }; - const rhs = Version{ - .major = version.major, - // .raw = version.raw - }; - return .{ - .left = .{ - .op = Op.lt, - .version = lhs, - }, - .right = .{ - .op = Op.gte, - .version = rhs, - }, - }; - }, - .patch => { - const lhs = Version{ - .major = version.major, - .minor = version.minor +| 1, - // .raw = version.raw; - }; - const rhs = Version{ - .major = version.major, - .minor = version.minor, - // .raw = version.raw; - }; - return Range{ - .left = .{ - .op = Op.lt, - .version = lhs, - }, - .right = .{ - .op = Op.gte, - .version = rhs, - }, - }; - }, - } - } - - pub inline fn hasLeft(this: Range) bool { - return this.left.op != Op.unset; - } - - pub inline fn hasRight(this: Range) bool { - return this.right.op != Op.unset; - } - - /// Is the Range equal to another Range - /// This does not evaluate the range. - pub inline fn eql(lhs: Range, rhs: Range) bool { - return lhs.left.eql(rhs.left) and lhs.right.eql(rhs.right); - } - - pub const Formatter = struct { - buffer: []const u8, - range: *const Range, - - pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - if (this.range.left.op == Op.unset and this.range.right.op == Op.unset) { - return; - } - - if (this.range.right.op == .unset) { - try std.fmt.format(writer, "{}", .{this.range.left.fmt(this.buffer)}); - } else { - try std.fmt.format(writer, "{} {}", .{ this.range.left.fmt(this.buffer), this.range.right.fmt(this.buffer) }); - } - } - }; - - pub fn fmt(this: *const Range, buf: []const u8) @This().Formatter { - return .{ .buffer = buf, .range = this }; - } - - pub const Comparator = struct { - op: Op = .unset, - version: Version = .{}, - - pub inline fn eql(lhs: Comparator, rhs: Comparator) bool { - return lhs.op == rhs.op and lhs.version.eql(rhs.version); - } - - pub const Formatter = struct { - buffer: []const u8, - comparator: *const Comparator, - - pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - if (this.comparator.op == Op.unset) { - return; - } - - switch (this.comparator.op) { - .unset => unreachable, // see above, - .eql => try writer.writeAll("=="), - .lt => try writer.writeAll("<"), - .lte => try writer.writeAll("<="), - .gt => try writer.writeAll(">"), - .gte => try writer.writeAll(">="), - } - - try std.fmt.format(writer, "{}", .{this.comparator.version.fmt(this.buffer)}); - } - }; - - pub fn fmt(this: *const Comparator, buf: []const u8) @This().Formatter { - return .{ .buffer = buf, .comparator = this }; - } - - pub fn satisfies( - comparator: Comparator, - version: Version, - comparator_buf: string, - version_buf: string, - ) bool { - const order = version.orderWithoutBuild(comparator.version, version_buf, comparator_buf); - - return switch (order) { - .eq => switch (comparator.op) { - .lte, .gte, .eql => true, - else => false, - }, - .gt => switch (comparator.op) { - .gt, .gte => true, - else => false, - }, - .lt => switch (comparator.op) { - .lt, .lte => true, - else => false, - }, - }; - } - }; - - pub fn satisfies(range: Range, version: Version, range_buf: string, version_buf: string) bool { - const has_left = range.hasLeft(); - const has_right = range.hasRight(); - - if (!has_left) { - return true; - } - - if (!range.left.satisfies(version, range_buf, version_buf)) { - return false; - } - - if (has_right and !range.right.satisfies(version, range_buf, version_buf)) { - return false; - } - - return true; - } - - pub fn satisfiesPre(range: Range, version: Version, range_buf: string, version_buf: string, pre_matched: *bool) bool { - if (comptime Environment.allow_assert) { - assert(version.tag.hasPre()); - } - const has_left = range.hasLeft(); - const has_right = range.hasRight(); - - if (!has_left) { - return true; - } - - // If left has prerelease check if major,minor,patch matches with left. If - // not, check the same with right if right exists and has prerelease. - pre_matched.* = pre_matched.* or - (range.left.version.tag.hasPre() and - version.patch == range.left.version.patch and - version.minor == range.left.version.minor and - version.major == range.left.version.major) or - (has_right and - range.right.version.tag.hasPre() and - version.patch == range.right.version.patch and - version.minor == range.right.version.minor and - version.major == range.right.version.major); - - if (!range.left.satisfies(version, range_buf, version_buf)) { - return false; - } - - if (has_right and !range.right.satisfies(version, range_buf, version_buf)) { - return false; - } - - return true; - } -}; - -/// Linked-list of AND ranges -/// "^1 ^2" -/// ----|----- -/// That is two Query -pub const Query = struct { - pub const Op = enum { - none, - AND, - OR, - }; - - range: Range = Range{}, - - // AND - next: ?*Query = null, - - const Formatter = struct { - query: *const Query, - buffer: []const u8, - pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - const this = formatter.query; - - if (this.next) |ptr| { - if (ptr.range.hasLeft() or ptr.range.hasRight()) { - try std.fmt.format(writer, "{} && {}", .{ this.range.fmt(formatter.buffer), ptr.range.fmt(formatter.buffer) }); - return; - } - } - - try std.fmt.format(writer, "{}", .{this.range.fmt(formatter.buffer)}); - } - }; - - pub fn fmt(this: *const Query, buf: []const u8) @This().Formatter { - return .{ .query = this, .buffer = buf }; - } - - /// Linked-list of Queries OR'd together - /// "^1 || ^2" - /// ----|----- - /// That is two List - pub const List = struct { - head: Query = Query{}, - tail: ?*Query = null, - - // OR - next: ?*List = null, - - const Formatter = struct { - list: *const List, - buffer: []const u8, - pub fn format(formatter: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - const this = formatter.list; - - if (this.next) |ptr| { - try std.fmt.format(writer, "{} || {}", .{ this.head.fmt(formatter.buffer), ptr.fmt(formatter.buffer) }); - } else { - try std.fmt.format(writer, "{}", .{this.head.fmt(formatter.buffer)}); - } - } - }; - - pub fn fmt(this: *const List, buf: []const u8) @This().Formatter { - return .{ .list = this, .buffer = buf }; - } - - pub fn satisfies(list: *const List, version: Version, list_buf: string, version_buf: string) bool { - return list.head.satisfies( - version, - list_buf, - version_buf, - ) or (list.next orelse return false).satisfies( - version, - list_buf, - version_buf, - ); - } - - pub fn satisfiesPre(list: *const List, version: Version, list_buf: string, version_buf: string) bool { - if (comptime Environment.allow_assert) { - assert(version.tag.hasPre()); - } - - // `version` has a prerelease tag: - // - needs to satisfy each comparator in the query ( AND AND ...) like normal comparison - // - if it does, also needs to match major, minor, patch with at least one of the other versions - // with a prerelease - // https://github.com/npm/node-semver/blob/ac9b35769ab0ddfefd5a3af4a3ecaf3da2012352/classes/range.js#L505 - var pre_matched = false; - return (list.head.satisfiesPre( - version, - list_buf, - version_buf, - &pre_matched, - ) and pre_matched) or (list.next orelse return false).satisfiesPre( - version, - list_buf, - version_buf, - ); - } - - pub fn eql(lhs: *const List, rhs: *const List) bool { - if (!lhs.head.eql(&rhs.head)) return false; - - const lhs_next = lhs.next orelse return rhs.next == null; - const rhs_next = rhs.next orelse return false; - - return lhs_next.eql(rhs_next); - } - - pub fn andRange(self: *List, allocator: Allocator, range: Range) !void { - if (!self.head.range.hasLeft() and !self.head.range.hasRight()) { - self.head.range = range; - return; - } - - var tail = try allocator.create(Query); - tail.* = Query{ - .range = range, - }; - tail.range = range; - - var last_tail = self.tail orelse &self.head; - last_tail.next = tail; - self.tail = tail; - } - }; - - pub const Group = struct { - head: List = List{}, - tail: ?*List = null, - allocator: Allocator, - input: string = "", - - flags: FlagsBitSet = FlagsBitSet.initEmpty(), - pub const Flags = struct { - pub const pre = 1; - pub const build = 0; - }; - - const Formatter = struct { - group: *const Group, - buf: string, - - pub fn format(formatter: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - const this = formatter.group; - - if (this.tail == null and this.head.tail == null and !this.head.head.range.hasLeft()) { - return; - } - - if (this.tail == null and this.head.tail == null) { - try std.fmt.format(writer, "{}", .{this.head.fmt(formatter.buf)}); - return; - } - - var list = &this.head; - while (list.next) |next| { - try std.fmt.format(writer, "{} && ", .{list.fmt(formatter.buf)}); - list = next; - } - - try std.fmt.format(writer, "{}", .{list.fmt(formatter.buf)}); - } - }; - - pub fn fmt(this: *const Group, buf: string) @This().Formatter { - return .{ - .group = this, - .buf = buf, - }; - } - - pub fn jsonStringify(this: *const Group, writer: anytype) !void { - const temp = try std.fmt.allocPrint(bun.default_allocator, "{}", .{this.fmt()}); - defer bun.default_allocator.free(temp); - try std.json.encodeJsonString(temp, .{}, writer); - } - - pub fn deinit(this: *const Group) void { - var list = this.head; - var allocator = this.allocator; - - while (list.next) |next| { - var query = list.head; - while (query.next) |next_query| { - query = next_query.*; - allocator.destroy(next_query); - } - list = next.*; - allocator.destroy(next); - } - } - - pub fn getExactVersion(this: *const Group) ?Version { - const range = this.head.head.range; - if (this.head.next == null and - this.head.head.next == null and - range.hasLeft() and - range.left.op == .eql and - !range.hasRight()) - { - if (comptime Environment.allow_assert) { - assert(this.tail == null); - } - return range.left.version; - } - - return null; - } - - pub fn from(version: Version) Group { - return .{ - .allocator = bun.default_allocator, - .head = .{ - .head = .{ - .range = .{ - .left = .{ - .op = .eql, - .version = version, - }, - }, - }, - }, - }; - } - - pub const FlagsBitSet = bun.bit_set.IntegerBitSet(3); - - pub fn isExact(this: *const Group) bool { - return this.head.next == null and this.head.head.next == null and !this.head.head.range.hasRight() and this.head.head.range.left.op == .eql; - } - - pub fn @"is *"(this: *const Group) bool { - const left = this.head.head.range.left; - return this.head.head.range.right.op == .unset and - left.op == .gte and - this.head.next == null and - this.head.head.next == null and - left.version.isZero() and - !this.flags.isSet(Flags.build); - } - - pub inline fn eql(lhs: Group, rhs: Group) bool { - return lhs.head.eql(&rhs.head); - } - - pub fn toVersion(this: Group) Version { - assert(this.isExact() or this.head.head.range.left.op == .unset); - return this.head.head.range.left.version; - } - - pub fn orVersion(self: *Group, version: Version) !void { - if (self.tail == null and !self.head.head.range.hasLeft()) { - self.head.head.range.left.version = version; - self.head.head.range.left.op = .eql; - return; - } - - var new_tail = try self.allocator.create(List); - new_tail.* = List{}; - new_tail.head.range.left.version = version; - new_tail.head.range.left.op = .eql; - - var prev_tail = self.tail orelse &self.head; - prev_tail.next = new_tail; - self.tail = new_tail; - } - - pub fn andRange(self: *Group, range: Range) !void { - var tail = self.tail orelse &self.head; - try tail.andRange(self.allocator, range); - } - - pub fn orRange(self: *Group, range: Range) !void { - if (self.tail == null and self.head.tail == null and !self.head.head.range.hasLeft()) { - self.head.head.range = range; - return; - } - - var new_tail = try self.allocator.create(List); - new_tail.* = List{}; - new_tail.head.range = range; - - var prev_tail = self.tail orelse &self.head; - prev_tail.next = new_tail; - self.tail = new_tail; - } - - pub inline fn satisfies( - group: *const Group, - version: Version, - group_buf: string, - version_buf: string, - ) bool { - return if (version.tag.hasPre()) - group.head.satisfiesPre(version, group_buf, version_buf) - else - group.head.satisfies(version, group_buf, version_buf); - } - }; - - pub fn eql(lhs: *const Query, rhs: *const Query) bool { - if (!lhs.range.eql(rhs.range)) return false; - - const lhs_next = lhs.next orelse return rhs.next == null; - const rhs_next = rhs.next orelse return false; - - return lhs_next.eql(rhs_next); - } - - pub fn satisfies(query: *const Query, version: Version, query_buf: string, version_buf: string) bool { - return query.range.satisfies( - version, - query_buf, - version_buf, - ) and (query.next orelse return true).satisfies( - version, - query_buf, - version_buf, - ); - } - - pub fn satisfiesPre(query: *const Query, version: Version, query_buf: string, version_buf: string, pre_matched: *bool) bool { - if (comptime Environment.allow_assert) { - assert(version.tag.hasPre()); - } - return query.range.satisfiesPre( - version, - query_buf, - version_buf, - pre_matched, - ) and (query.next orelse return true).satisfiesPre( - version, - query_buf, - version_buf, - pre_matched, - ); - } - - const Token = struct { - tag: Tag = Tag.none, - wildcard: Wildcard = Wildcard.none, - - pub fn toRange(this: Token, version: Version.Partial) Range { - switch (this.tag) { - // Allows changes that do not modify the left-most non-zero element in the [major, minor, patch] tuple - .caret => { - // https://github.com/npm/node-semver/blob/3a8a4309ae986c1967b3073ba88c9e69433d44cb/classes/range.js#L302-L353 - var range = Range{}; - if (version.major) |major| done: { - range.left = .{ - .op = .gte, - .version = .{ - .major = major, - }, - }; - range.right = .{ - .op = .lt, - }; - if (version.minor) |minor| { - range.left.version.minor = minor; - if (version.patch) |patch| { - range.left.version.patch = patch; - range.left.version.tag = version.tag; - if (major == 0) { - if (minor == 0) { - range.right.version.patch = patch +| 1; - } else { - range.right.version.minor = minor +| 1; - } - break :done; - } - } else if (major == 0) { - range.right.version.minor = minor +| 1; - break :done; - } - } - range.right.version.major = major +| 1; - } - return range; - }, - .tilda => { - // https://github.com/npm/node-semver/blob/3a8a4309ae986c1967b3073ba88c9e69433d44cb/classes/range.js#L261-L287 - var range = Range{}; - if (version.major) |major| done: { - range.left = .{ - .op = .gte, - .version = .{ - .major = major, - }, - }; - range.right = .{ - .op = .lt, - }; - if (version.minor) |minor| { - range.left.version.minor = minor; - if (version.patch) |patch| { - range.left.version.patch = patch; - range.left.version.tag = version.tag; - } - range.right.version.major = major; - range.right.version.minor = minor +| 1; - break :done; - } - range.right.version.major = major +| 1; - } - return range; - }, - .none => unreachable, - .version => { - if (this.wildcard != Wildcard.none) { - return Range.initWildcard(version.min(), this.wildcard); - } - - return .{ .left = .{ .op = .eql, .version = version.min() } }; - }, - else => {}, - } - - return switch (this.wildcard) { - .major => .{ - .left = .{ .op = .gte, .version = version.min() }, - .right = .{ - .op = .lte, - .version = .{ - .major = std.math.maxInt(u32), - .minor = std.math.maxInt(u32), - .patch = std.math.maxInt(u32), - }, - }, - }, - .minor => switch (this.tag) { - .lte => .{ - .left = .{ - .op = .lte, - .version = .{ - .major = version.major orelse 0, - .minor = std.math.maxInt(u32), - .patch = std.math.maxInt(u32), - }, - }, - }, - .lt => .{ - .left = .{ - .op = .lt, - .version = .{ - .major = version.major orelse 0, - .minor = 0, - .patch = 0, - }, - }, - }, - - .gt => .{ - .left = .{ - .op = .gt, - .version = .{ - .major = version.major orelse 0, - .minor = std.math.maxInt(u32), - .patch = std.math.maxInt(u32), - }, - }, - }, - - .gte => .{ - .left = .{ - .op = .gte, - .version = .{ - .major = version.major orelse 0, - .minor = 0, - .patch = 0, - }, - }, - }, - else => unreachable, - }, - .patch => switch (this.tag) { - .lte => .{ - .left = .{ - .op = .lte, - .version = .{ - .major = version.major orelse 0, - .minor = version.minor orelse 0, - .patch = std.math.maxInt(u32), - }, - }, - }, - .lt => .{ - .left = .{ - .op = .lt, - .version = .{ - .major = version.major orelse 0, - .minor = version.minor orelse 0, - .patch = 0, - }, - }, - }, - - .gt => .{ - .left = .{ - .op = .gt, - .version = .{ - .major = version.major orelse 0, - .minor = version.minor orelse 0, - .patch = std.math.maxInt(u32), - }, - }, - }, - - .gte => .{ - .left = .{ - .op = .gte, - .version = .{ - .major = version.major orelse 0, - .minor = version.minor orelse 0, - .patch = 0, - }, - }, - }, - else => unreachable, - }, - .none => .{ - .left = .{ - .op = switch (this.tag) { - .gt => .gt, - .gte => .gte, - .lt => .lt, - .lte => .lte, - else => unreachable, - }, - .version = version.min(), - }, - }, - }; - } - - pub const Tag = enum { - none, - gt, - gte, - lt, - lte, - version, - tilda, - caret, - }; - - pub const Wildcard = enum { - none, - major, - minor, - patch, - }; - }; - - pub fn parse( - allocator: Allocator, - input: string, - sliced: SlicedString, - ) bun.OOM!Group { - var i: usize = 0; - var list = Group{ - .allocator = allocator, - .input = input, - }; - - var token = Token{}; - var prev_token = Token{}; - - var count: u8 = 0; - var skip_round = false; - var is_or = false; - - while (i < input.len) { - skip_round = false; - - switch (input[i]) { - '>' => { - if (input.len > i + 1 and input[i + 1] == '=') { - token.tag = .gte; - i += 1; - } else { - token.tag = .gt; - } - - i += 1; - while (i < input.len and input[i] == ' ') : (i += 1) {} - }, - '<' => { - if (input.len > i + 1 and input[i + 1] == '=') { - token.tag = .lte; - i += 1; - } else { - token.tag = .lt; - } - - i += 1; - while (i < input.len and input[i] == ' ') : (i += 1) {} - }, - '=', 'v' => { - token.tag = .version; - is_or = true; - i += 1; - while (i < input.len and input[i] == ' ') : (i += 1) {} - }, - '~' => { - token.tag = .tilda; - i += 1; - - if (i < input.len and input[i] == '>') i += 1; - - while (i < input.len and input[i] == ' ') : (i += 1) {} - }, - '^' => { - token.tag = .caret; - i += 1; - while (i < input.len and input[i] == ' ') : (i += 1) {} - }, - '0'...'9', 'X', 'x', '*' => { - token.tag = .version; - is_or = true; - }, - '|' => { - i += 1; - - while (i < input.len and input[i] == '|') : (i += 1) {} - while (i < input.len and input[i] == ' ') : (i += 1) {} - is_or = true; - token.tag = Token.Tag.none; - skip_round = true; - }, - '-' => { - i += 1; - while (i < input.len and input[i] == ' ') : (i += 1) {} - }, - ' ' => { - i += 1; - while (i < input.len and input[i] == ' ') : (i += 1) {} - skip_round = true; - }, - else => { - i += 1; - token.tag = Token.Tag.none; - - // skip tagged versions - // we are assuming this is the beginning of a tagged version like "boop" - // "1.0.0 || boop" - while (i < input.len and input[i] != ' ' and input[i] != '|') : (i += 1) {} - skip_round = true; - }, - } - - if (!skip_round) { - const parse_result = Version.parse(sliced.sub(input[i..])); - const version = parse_result.version.min(); - if (version.tag.hasBuild()) list.flags.setValue(Group.Flags.build, true); - if (version.tag.hasPre()) list.flags.setValue(Group.Flags.pre, true); - - token.wildcard = parse_result.wildcard; - - i += parse_result.len; - const rollback = i; - - const maybe_hyphenate = i < input.len and (input[i] == ' ' or input[i] == '-'); - - // TODO: can we do this without rolling back? - const hyphenate: bool = maybe_hyphenate and possibly_hyphenate: { - i += strings.lengthOfLeadingWhitespaceASCII(input[i..]); - if (!(i < input.len and input[i] == '-')) break :possibly_hyphenate false; - i += 1; - i += strings.lengthOfLeadingWhitespaceASCII(input[i..]); - if (i == input.len) break :possibly_hyphenate false; - if (input[i] == 'v' or input[i] == '=') { - i += 1; - } - if (i == input.len) break :possibly_hyphenate false; - i += strings.lengthOfLeadingWhitespaceASCII(input[i..]); - if (i == input.len) break :possibly_hyphenate false; - - if (!(i < input.len and switch (input[i]) { - '0'...'9', 'X', 'x', '*' => true, - else => false, - })) break :possibly_hyphenate false; - - break :possibly_hyphenate true; - }; - - if (!hyphenate) i = rollback; - i += @as(usize, @intFromBool(!hyphenate)); - - if (hyphenate) { - const second_parsed = Version.parse(sliced.sub(input[i..])); - var second_version = second_parsed.version.min(); - if (second_version.tag.hasBuild()) list.flags.setValue(Group.Flags.build, true); - if (second_version.tag.hasPre()) list.flags.setValue(Group.Flags.pre, true); - const range: Range = brk: { - switch (second_parsed.wildcard) { - .major => { - // "1.0.0 - x" --> ">=1.0.0" - break :brk Range{ - .left = .{ .op = .gte, .version = version }, - }; - }, - .minor => { - // "1.0.0 - 1.x" --> ">=1.0.0 < 2.0.0" - second_version.major +|= 1; - second_version.minor = 0; - second_version.patch = 0; - - break :brk Range{ - .left = .{ .op = .gte, .version = version }, - .right = .{ .op = .lt, .version = second_version }, - }; - }, - .patch => { - // "1.0.0 - 1.0.x" --> ">=1.0.0 <1.1.0" - second_version.minor +|= 1; - second_version.patch = 0; - - break :brk Range{ - .left = .{ .op = .gte, .version = version }, - .right = .{ .op = .lt, .version = second_version }, - }; - }, - .none => { - break :brk Range{ - .left = .{ .op = .gte, .version = version }, - .right = .{ .op = .lte, .version = second_version }, - }; - }, - } - }; - - if (is_or) { - try list.orRange(range); - } else { - try list.andRange(range); - } - - i += second_parsed.len + 1; - } else if (count == 0 and token.tag == .version) { - switch (parse_result.wildcard) { - .none => { - try list.orVersion(version); - }, - else => { - try list.orRange(token.toRange(parse_result.version)); - }, - } - } else if (count == 0) { - // From a semver perspective, treat "--foo" the same as "-foo" - // example: foo/bar@1.2.3@--canary.24 - // ^ - if (token.tag == .none) { - is_or = false; - token.wildcard = .none; - prev_token.tag = .none; - continue; - } - try list.andRange(token.toRange(parse_result.version)); - } else if (is_or) { - try list.orRange(token.toRange(parse_result.version)); - } else { - try list.andRange(token.toRange(parse_result.version)); - } - - is_or = false; - count += 1; - token.wildcard = .none; - prev_token.tag = token.tag; - } - } - - return list; - } -}; - -pub const SemverObject = struct { - pub fn create(globalThis: *JSC.JSGlobalObject) JSC.JSValue { - const object = JSC.JSValue.createEmptyObject(globalThis, 2); - - object.put( - globalThis, - JSC.ZigString.static("satisfies"), - JSC.NewFunction( - globalThis, - JSC.ZigString.static("satisfies"), - 2, - SemverObject.satisfies, - false, - ), - ); - - object.put( - globalThis, - JSC.ZigString.static("order"), - JSC.NewFunction( - globalThis, - JSC.ZigString.static("order"), - 2, - SemverObject.order, - false, - ), - ); - - return object; - } - - pub fn order( - globalThis: *JSC.JSGlobalObject, - callFrame: *JSC.CallFrame, - ) bun.JSError!JSC.JSValue { - var arena = std.heap.ArenaAllocator.init(bun.default_allocator); - defer arena.deinit(); - var stack_fallback = std.heap.stackFallback(512, arena.allocator()); - const allocator = stack_fallback.get(); - - const arguments = callFrame.arguments_old(2).slice(); - if (arguments.len < 2) { - return globalThis.throw("Expected two arguments", .{}); - } - - const left_arg = arguments[0]; - const right_arg = arguments[1]; - - const left_string = left_arg.toStringOrNull(globalThis) orelse return JSC.jsNumber(0); - const right_string = right_arg.toStringOrNull(globalThis) orelse return JSC.jsNumber(0); - - const left = left_string.toSlice(globalThis, allocator); - defer left.deinit(); - const right = right_string.toSlice(globalThis, allocator); - defer right.deinit(); - - if (!strings.isAllASCII(left.slice())) return JSC.jsNumber(0); - if (!strings.isAllASCII(right.slice())) return JSC.jsNumber(0); - - const left_result = Version.parse(SlicedString.init(left.slice(), left.slice())); - const right_result = Version.parse(SlicedString.init(right.slice(), right.slice())); - - if (!left_result.valid) { - return globalThis.throw("Invalid SemVer: {s}\n", .{left.slice()}); - } - - if (!right_result.valid) { - return globalThis.throw("Invalid SemVer: {s}\n", .{right.slice()}); - } - - const left_version = left_result.version.max(); - const right_version = right_result.version.max(); - - return switch (left_version.orderWithoutBuild(right_version, left.slice(), right.slice())) { - .eq => JSC.jsNumber(0), - .gt => JSC.jsNumber(1), - .lt => JSC.jsNumber(-1), - }; - } - - pub fn satisfies(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSC.JSValue { - var arena = std.heap.ArenaAllocator.init(bun.default_allocator); - defer arena.deinit(); - var stack_fallback = std.heap.stackFallback(512, arena.allocator()); - const allocator = stack_fallback.get(); - - const arguments = callFrame.arguments_old(2).slice(); - if (arguments.len < 2) { - return globalThis.throw("Expected two arguments", .{}); - } - - const left_arg = arguments[0]; - const right_arg = arguments[1]; - - const left_string = left_arg.toStringOrNull(globalThis) orelse return .zero; - const right_string = right_arg.toStringOrNull(globalThis) orelse return .zero; - - const left = left_string.toSlice(globalThis, allocator); - defer left.deinit(); - const right = right_string.toSlice(globalThis, allocator); - defer right.deinit(); - - if (!strings.isAllASCII(left.slice())) return .false; - if (!strings.isAllASCII(right.slice())) return .false; - - const left_result = Version.parse(SlicedString.init(left.slice(), left.slice())); - if (left_result.wildcard != .none) { - return .false; - } - - const left_version = left_result.version.min(); - - const right_group = try Query.parse( - allocator, - right.slice(), - SlicedString.init(right.slice(), right.slice()), - ); - defer right_group.deinit(); - - const right_version = right_group.getExactVersion(); - - if (right_version != null) { - return JSC.jsBoolean(left_version.eql(right_version.?)); - } - - return JSC.jsBoolean(right_group.satisfies(left_version, right.slice(), left.slice())); - } -}; - -const assert = bun.assert; diff --git a/src/install/versioned_url.zig b/src/install/versioned_url.zig index ac31f98ece1521..917c03ee303723 100644 --- a/src/install/versioned_url.zig +++ b/src/install/versioned_url.zig @@ -1,5 +1,6 @@ -const Semver = @import("./semver.zig"); -const String = @import("./semver.zig").String; +const bun = @import("root").bun; +const Semver = bun.Semver; +const String = Semver.String; pub const VersionedURL = extern struct { url: String, diff --git a/src/install/windows-shim/BinLinkingShim.zig b/src/install/windows-shim/BinLinkingShim.zig index 219e13dc16779e..b4000502bcdb31 100644 --- a/src/install/windows-shim/BinLinkingShim.zig +++ b/src/install/windows-shim/BinLinkingShim.zig @@ -77,6 +77,7 @@ pub const Flags = packed struct(u16) { pub const embedded_executable_data = @embedFile("bun_shim_impl.exe"); fn wU8(comptime s: []const u8) []const u8 { + @setEvalBranchQuota(1_000_000); const str = std.unicode.utf8ToUtf16LeStringLiteral(s); return @alignCast(std.mem.sliceAsBytes(str)); } diff --git a/src/install/windows-shim/bun_shim_impl.zig b/src/install/windows-shim/bun_shim_impl.zig index a40d7780d9df54..e3d78724136aa2 100644 --- a/src/install/windows-shim/bun_shim_impl.zig +++ b/src/install/windows-shim/bun_shim_impl.zig @@ -44,7 +44,7 @@ const dbg = builtin.mode == .Debug; const std = @import("std"); const w = std.os.windows; const assert = std.debug.assert; -const fmt16 = std.unicode.fmtUtf16le; +const fmt16 = std.unicode.fmtUtf16Le; const is_standalone = @import("root") == @This(); const bun = if (!is_standalone) @import("root").bun else @compileError("cannot use 'bun' in standalone build of bun_shim_impl"); @@ -260,7 +260,7 @@ var failure_reason_data: [512]u8 = undefined; var failure_reason_argument: ?[]const u8 = null; noinline fn failAndExitWithReason(reason: FailReason) noreturn { - @setCold(true); + @branchHint(.cold); const console_handle = w.teb().ProcessEnvironmentBlock.ProcessParameters.hStdError; var mode: w.DWORD = 0; @@ -310,7 +310,7 @@ pub const LauncherMode = enum { } noinline fn fail(comptime mode: LauncherMode, comptime reason: FailReason) mode.FailRetType() { - @setCold(true); + @branchHint(.cold); return switch (mode) { .launch => failAndExitWithReason(reason), .read_without_launch => ReadWithoutLaunchResult{ .err = reason }, @@ -363,8 +363,8 @@ fn launcher(comptime mode: LauncherMode, bun_ctx: anytype) mode.RetType() { const suffix = comptime (if (is_standalone) wliteral("exe") else wliteral("bunx")); if (dbg) if (!std.mem.endsWith(u16, image_path_u16, suffix)) { std.debug.panic("assert failed: image path expected to end with {}, got {}", .{ - std.unicode.fmtUtf16le(suffix), - std.unicode.fmtUtf16le(image_path_u16), + std.unicode.fmtUtf16Le(suffix), + std.unicode.fmtUtf16Le(image_path_u16), }); }; const image_path_to_copy_b_len = image_path_b_len - 2 * suffix.len; @@ -487,7 +487,7 @@ fn launcher(comptime mode: LauncherMode, bun_ctx: anytype) mode.RetType() { assert(ptr[1] == '.'); while (true) { - if (dbg) debug("1 - {}", .{std.unicode.fmtUtf16le(ptr[0..1])}); + if (dbg) debug("1 - {}", .{std.unicode.fmtUtf16Le(ptr[0..1])}); if (ptr[0] == '\\') { left -= 1; // ptr is of type [*]u16, which means -= operates on number of ITEMS, not BYTES @@ -505,7 +505,7 @@ fn launcher(comptime mode: LauncherMode, bun_ctx: anytype) mode.RetType() { // inlined loop to do this again, because the completion case is different // using `inline for` caused comptime issues that made the code much harder to read while (true) { - if (dbg) debug("2 - {}", .{std.unicode.fmtUtf16le(ptr[0..1])}); + if (dbg) debug("2 - {}", .{std.unicode.fmtUtf16Le(ptr[0..1])}); if (ptr[0] == '\\') { // ptr is at the position marked S, so move forward one *character* break :brk ptr + 1; diff --git a/src/io/PipeReader.zig b/src/io/PipeReader.zig index 668f7b55fe2f7d..04342020bb58d4 100644 --- a/src/io/PipeReader.zig +++ b/src/io/PipeReader.zig @@ -972,7 +972,7 @@ pub const WindowsBufferedReader = struct { parent: *anyopaque = undefined, vtable: WindowsOutputReaderVTable = undefined, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(@This(), deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); const WindowsOutputReader = @This(); @@ -1017,6 +1017,8 @@ pub const WindowsBufferedReader = struct { .source = other.source, }; other.flags.is_done = true; + other._offset = 0; + other.buffer().* = std.ArrayList(u8).init(bun.default_allocator); other.source = null; to.setParent(parent); } diff --git a/src/io/PipeWriter.zig b/src/io/PipeWriter.zig index 622fda152768a9..024d78bfc75709 100644 --- a/src/io/PipeWriter.zig +++ b/src/io/PipeWriter.zig @@ -4,9 +4,10 @@ const Async = bun.Async; const JSC = bun.JSC; const uv = bun.windows.libuv; const Source = @import("./source.zig").Source; - const log = bun.Output.scoped(.PipeWriter, true); const FileType = @import("./pipes.zig").FileType; +const OOM = bun.OOM; +const Environment = bun.Environment; pub const WriteResult = union(enum) { done: usize, @@ -35,41 +36,41 @@ pub fn PosixPipeWriter( ) type { _ = onWritable; // autofix return struct { - pub fn _tryWrite(this: *This, buf_: []const u8) WriteResult { - return switch (getFileType(this)) { + pub fn _tryWrite(this: *This, force_sync: bool, buf_: []const u8) WriteResult { + return switch (if (!force_sync) getFileType(this) else .file) { inline else => |ft| return _tryWriteWithWriteFn(this, buf_, comptime writeToFileType(ft)), }; } - fn _tryWriteWithWriteFn(this: *This, buf_: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult { + fn _tryWriteWithWriteFn(this: *This, buf: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult { const fd = getFd(this); - var buf = buf_; - while (buf.len > 0) { - switch (write_fn(fd, buf)) { + var offset: usize = 0; + + while (offset < buf.len) { + switch (write_fn(fd, buf[offset..])) { .err => |err| { if (err.isRetry()) { - return .{ .pending = buf_.len - buf.len }; + return .{ .pending = offset }; } if (err.getErrno() == .PIPE) { - return .{ .done = buf_.len - buf.len }; + return .{ .done = offset }; } return .{ .err = err }; }, .result => |wrote| { + offset += wrote; if (wrote == 0) { - return .{ .done = buf_.len - buf.len }; + return .{ .done = offset }; } - - buf = buf[wrote..]; }, } } - return .{ .wrote = buf_.len - buf.len }; + return .{ .wrote = offset }; } fn writeToFileType(comptime file_type: FileType) *const (fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) { @@ -138,45 +139,39 @@ pub fn PosixPipeWriter( } } - pub fn drainBufferedData(parent: *This, input_buffer: []const u8, max_write_size: usize, received_hup: bool) WriteResult { + pub fn drainBufferedData(parent: *This, buf: []const u8, max_write_size: usize, received_hup: bool) WriteResult { _ = received_hup; // autofix - var buf = input_buffer; - buf = if (max_write_size < buf.len and max_write_size > 0) buf[0..max_write_size] else buf; - const original_buf = buf; - while (buf.len > 0) { - const attempt = _tryWrite(parent, buf); + const trimmed = if (max_write_size < buf.len and max_write_size > 0) buf[0..max_write_size] else buf; + + var drained: usize = 0; + + while (drained < trimmed.len) { + const attempt = _tryWrite(parent, parent.getForceSync(), trimmed[drained..]); switch (attempt) { .pending => |pending| { - return .{ .pending = pending + (original_buf.len - buf.len) }; + drained += pending; + return .{ .pending = drained }; }, .wrote => |amt| { - buf = buf[amt..]; + drained += amt; }, .err => |err| { - const wrote = original_buf.len - buf.len; - if (err.isRetry()) { - return .{ .pending = wrote }; - } - - if (wrote > 0) { + if (drained > 0) { onError(parent, err); - return .{ .wrote = wrote }; + return .{ .wrote = drained }; } else { return .{ .err = err }; } }, .done => |amt| { - buf = buf[amt..]; - const wrote = original_buf.len - buf.len; - - return .{ .done = wrote }; + drained += amt; + return .{ .done = drained }; }, } } - const wrote = original_buf.len - buf.len; - return .{ .wrote = wrote }; + return .{ .wrote = drained }; } }; } @@ -236,6 +231,10 @@ pub fn PosixBufferedWriter( this.close(); } + pub fn getForceSync(_: *const @This()) bool { + return false; + } + fn _onWrite( this: *PosixWriter, written: usize, @@ -274,8 +273,6 @@ pub fn PosixBufferedWriter( } } - pub const tryWrite = @This()._tryWrite; - pub fn hasRef(this: *PosixWriter) bool { if (this.is_done) { return false; @@ -386,19 +383,23 @@ pub fn PosixStreamingWriter( comptime onClose: fn (*Parent) void, ) type { return struct { - // TODO: replace buffer + head for StreamBuffer - buffer: std.ArrayList(u8) = std.ArrayList(u8).init(bun.default_allocator), + outgoing: StreamBuffer = .{}, handle: PollOrFd = .{ .closed = {} }, parent: *Parent = undefined, - head: usize = 0, is_done: bool = false, closed_without_reporting: bool = false, - // TODO: - chunk_size: usize = 0, + force_sync: bool = false, + + pub fn getForceSync(this: *const @This()) bool { + return this.force_sync; + } + + // TODO: configurable? + const chunk_size: usize = std.mem.page_size; pub fn memoryCost(this: *const @This()) usize { - return @sizeOf(@This()) + this.buffer.capacity; + return @sizeOf(@This()) + this.outgoing.memoryCost(); } pub fn getPoll(this: *@This()) ?*Async.FilePoll { @@ -415,10 +416,18 @@ pub fn PosixStreamingWriter( return poll.fileType(); } + pub fn hasPendingData(this: *const PosixWriter) bool { + return this.outgoing.isNotEmpty(); + } + + pub fn shouldBuffer(this: *const PosixWriter, addition: usize) bool { + return !this.force_sync and this.outgoing.size() + addition < chunk_size; + } + const PosixWriter = @This(); - pub fn getBuffer(this: *PosixWriter) []const u8 { - return this.buffer.items[this.head..]; + pub fn getBuffer(this: *const PosixWriter) []const u8 { + return this.outgoing.slice(); } fn _onError( @@ -429,6 +438,7 @@ pub fn PosixStreamingWriter( this.closeWithoutReporting(); this.is_done = true; + this.outgoing.reset(); onError(@alignCast(@ptrCast(this.parent)), err); this.close(); @@ -439,19 +449,18 @@ pub fn PosixStreamingWriter( written: usize, status: WriteStatus, ) void { - this.head += written; + this.outgoing.wrote(written); if (status == .end_of_file and !this.is_done) { this.closeWithoutReporting(); } - if (this.buffer.items.len == this.head) { - if (this.buffer.capacity > 1024 * 1024 and status != .end_of_file) { - this.buffer.clearAndFree(); - } else { - this.buffer.clearRetainingCapacity(); + if (this.outgoing.isEmpty()) { + this.outgoing.cursor = 0; + if (status != .end_of_file) { + this.outgoing.maybeShrink(); } - this.head = 0; + this.outgoing.list.clearRetainingCapacity(); } onWrite(@ptrCast(this.parent), written, status); @@ -467,16 +476,13 @@ pub fn PosixStreamingWriter( return; } - this.head = 0; + this.outgoing.reset(); + if (onReady) |cb| { cb(@ptrCast(this.parent)); } } - pub fn hasPendingData(this: *const PosixWriter) bool { - return this.buffer.items.len > 0; - } - fn closeWithoutReporting(this: *PosixWriter) void { if (this.getFd() != bun.invalid_fd) { bun.assert(!this.closed_without_reporting); @@ -496,42 +502,20 @@ pub fn PosixStreamingWriter( } } - pub fn tryWrite(this: *PosixWriter, buf: []const u8) WriteResult { - if (this.is_done or this.closed_without_reporting) { - return .{ .done = 0 }; - } - - if (this.buffer.items.len > 0) { - this.buffer.appendSlice(buf) catch { - return .{ .err = bun.sys.Error.oom }; - }; - - return .{ .pending = 0 }; - } - - return @This()._tryWrite(this, buf); - } - pub fn writeUTF16(this: *PosixWriter, buf: []const u16) WriteResult { if (this.is_done or this.closed_without_reporting) { return .{ .done = 0 }; } - const had_buffered_data = this.buffer.items.len > 0; - { - var byte_list = bun.ByteList.fromList(this.buffer); - defer this.buffer = byte_list.listManaged(bun.default_allocator); + const before_len = this.outgoing.size(); - _ = byte_list.writeUTF16(bun.default_allocator, buf) catch { - return .{ .err = bun.sys.Error.oom }; - }; - } + this.outgoing.writeUTF16(buf) catch { + return .{ .err = bun.sys.Error.oom }; + }; - if (had_buffered_data) { - return .{ .pending = 0 }; - } + const buf_len = this.outgoing.size() - before_len; - return this._tryWriteNewlyBufferedData(); + return this._maybeWriteNewlyBufferedData(buf_len); } pub fn writeLatin1(this: *PosixWriter, buf: []const u8) WriteResult { @@ -543,42 +527,62 @@ pub fn PosixStreamingWriter( return this.write(buf); } - const had_buffered_data = this.buffer.items.len > 0; - { - var byte_list = bun.ByteList.fromList(this.buffer); - defer this.buffer = byte_list.listManaged(bun.default_allocator); + const before_len = this.outgoing.size(); - _ = byte_list.writeLatin1(bun.default_allocator, buf) catch { - return .{ .err = bun.sys.Error.oom }; - }; - } + const check_ascii = false; + this.outgoing.writeLatin1(buf, check_ascii) catch { + return .{ .err = bun.sys.Error.oom }; + }; - if (had_buffered_data) { - return .{ .pending = 0 }; + const buf_len = this.outgoing.size() - before_len; + + return this._maybeWriteNewlyBufferedData(buf_len); + } + + fn _maybeWriteNewlyBufferedData(this: *PosixWriter, buf_len: usize) WriteResult { + bun.assert(!this.is_done); + + if (this.shouldBuffer(0)) { + onWrite(this.parent, buf_len, .drained); + registerPoll(this); + + return .{ .wrote = buf_len }; } - return this._tryWriteNewlyBufferedData(); + return @This()._tryWriteNewlyBufferedData(this, this.outgoing.slice()); } - fn _tryWriteNewlyBufferedData(this: *PosixWriter) WriteResult { + fn _tryWriteNewlyBufferedData(this: *PosixWriter, buf: []const u8) WriteResult { bun.assert(!this.is_done); - switch (@This()._tryWrite(this, this.buffer.items)) { + const rc = @This()._tryWrite(this, this.force_sync, buf); + + switch (rc) { .wrote => |amt| { - if (amt == this.buffer.items.len) { - this.buffer.clearRetainingCapacity(); + if (amt == this.outgoing.size()) { + this.outgoing.reset(); + onWrite(this.parent, amt, .drained); } else { - this.head = amt; + this.outgoing.wrote(amt); + onWrite(this.parent, amt, .pending); + registerPoll(this); + return .{ .pending = amt }; } - return .{ .wrote = amt }; }, .done => |amt| { - this.buffer.clearRetainingCapacity(); - - return .{ .done = amt }; + this.outgoing.reset(); + onWrite(this.parent, amt, .end_of_file); }, + .pending => |amt| { + this.outgoing.wrote(amt); + onWrite(this.parent, amt, .pending); + registerPoll(this); + }, + else => |r| return r, } + + return rc; } pub fn write(this: *PosixWriter, buf: []const u8) WriteResult { @@ -586,39 +590,57 @@ pub fn PosixStreamingWriter( return .{ .done = 0 }; } - if (this.buffer.items.len + buf.len < this.chunk_size) { - this.buffer.appendSlice(buf) catch { + if (this.shouldBuffer(buf.len)) { + + // this is streaming, but we buffer the data below `chunk_size` to + // reduce the number of writes + this.outgoing.write(buf) catch { return .{ .err = bun.sys.Error.oom }; }; - return .{ .pending = 0 }; + // noop, but need this to have a chance + // to register deferred tasks (onAutoFlush) + onWrite(this.parent, buf.len, .drained); + registerPoll(this); + + // it's buffered, but should be reported as written to + // callers + return .{ .wrote = buf.len }; } - const rc = @This()._tryWrite(this, buf); - this.head = 0; + if (this.outgoing.size() > 0) { + // make sure write is in-order + this.outgoing.write(buf) catch { + return .{ .err = bun.sys.Error.oom }; + }; + + return this._tryWriteNewlyBufferedData(this.outgoing.slice()); + } + + const rc = @This()._tryWrite(this, this.force_sync, buf); + switch (rc) { .pending => |amt| { - this.buffer.appendSlice(buf[amt..]) catch { + this.outgoing.write(buf[amt..]) catch { return .{ .err = bun.sys.Error.oom }; }; - onWrite(this.parent, amt, .pending); - registerPoll(this); }, .wrote => |amt| { if (amt < buf.len) { - this.buffer.appendSlice(buf[amt..]) catch { + this.outgoing.write(buf[amt..]) catch { return .{ .err = bun.sys.Error.oom }; }; onWrite(this.parent, amt, .pending); + registerPoll(this); } else { - this.buffer.clearRetainingCapacity(); + this.outgoing.reset(); onWrite(this.parent, amt, .drained); } }, .done => |amt| { - this.buffer.clearRetainingCapacity(); + this.outgoing.reset(); onWrite(this.parent, amt, .end_of_file); return .{ .done = amt }; }, @@ -635,8 +657,9 @@ pub fn PosixStreamingWriter( return .{ .done = 0 }; } - const buffer = this.buffer.items; + const buffer = this.getBuffer(); if (buffer.len == 0) { + this.outgoing.reset(); return .{ .wrote = 0 }; } @@ -650,21 +673,26 @@ pub fn PosixStreamingWriter( // update head switch (rc) { .pending => |written| { - this.head += written; + this.outgoing.wrote(written); + if (this.outgoing.isEmpty()) { + this.outgoing.reset(); + } }, .wrote => |written| { - this.head += written; + this.outgoing.wrote(written); + if (this.outgoing.isEmpty()) { + this.outgoing.reset(); + } }, - .done => |written| { - this.head += written; + else => { + this.outgoing.reset(); }, - else => {}, } return rc; } pub fn deinit(this: *PosixWriter) void { - this.buffer.clearAndFree(); + this.outgoing.deinit(); this.closeWithoutReporting(); } @@ -1023,18 +1051,23 @@ pub fn WindowsBufferedWriter( }; } -/// Basic std.ArrayList(u8) + u32 cursor wrapper +/// Basic std.ArrayList(u8) + usize cursor wrapper pub const StreamBuffer = struct { list: std.ArrayList(u8) = std.ArrayList(u8).init(bun.default_allocator), - // should cursor be usize? - cursor: u32 = 0, + cursor: usize = 0, pub fn reset(this: *StreamBuffer) void { this.cursor = 0; - if (this.list.capacity > 32 * 1024) { + this.maybeShrink(); + this.list.clearRetainingCapacity(); + } + + pub fn maybeShrink(this: *StreamBuffer) void { + if (this.list.capacity > std.mem.page_size) { + // workaround insane zig decision to make it undefined behavior to resize .len < .capacity + this.list.expandToCapacity(); this.list.shrinkAndFree(std.mem.page_size); } - this.list.clearRetainingCapacity(); } pub fn memoryCost(this: *const StreamBuffer) usize { @@ -1053,24 +1086,28 @@ pub const StreamBuffer = struct { return this.size() > 0; } - pub fn write(this: *StreamBuffer, buffer: []const u8) !void { + pub fn write(this: *StreamBuffer, buffer: []const u8) OOM!void { _ = try this.list.appendSlice(buffer); } + pub fn wrote(this: *StreamBuffer, amount: usize) void { + this.cursor += amount; + } + pub fn writeAssumeCapacity(this: *StreamBuffer, buffer: []const u8) void { var byte_list = bun.ByteList.fromList(this.list); defer this.list = byte_list.listManaged(this.list.allocator); byte_list.appendSliceAssumeCapacity(buffer); } - pub fn ensureUnusedCapacity(this: *StreamBuffer, capacity: usize) !void { + pub fn ensureUnusedCapacity(this: *StreamBuffer, capacity: usize) OOM!void { var byte_list = bun.ByteList.fromList(this.list); defer this.list = byte_list.listManaged(this.list.allocator); _ = try byte_list.ensureUnusedCapacity(this.list.allocator, capacity); } - pub fn writeTypeAsBytes(this: *StreamBuffer, comptime T: type, data: *const T) !void { + pub fn writeTypeAsBytes(this: *StreamBuffer, comptime T: type, data: *const T) OOM!void { _ = try this.write(std.mem.asBytes(data)); } @@ -1080,7 +1117,7 @@ pub const StreamBuffer = struct { byte_list.writeTypeAsBytesAssumeCapacity(T, data); } - pub fn writeOrFallback(this: *StreamBuffer, buffer: anytype, comptime writeFn: anytype) ![]const u8 { + pub fn writeOrFallback(this: *StreamBuffer, buffer: anytype, comptime writeFn: anytype) OOM![]const u8 { if (comptime @TypeOf(writeFn) == @TypeOf(&writeLatin1) and writeFn == &writeLatin1) { if (bun.strings.isAllASCII(buffer)) { return buffer; @@ -1109,9 +1146,11 @@ pub const StreamBuffer = struct { } } - pub fn writeLatin1(this: *StreamBuffer, buffer: []const u8) !void { - if (bun.strings.isAllASCII(buffer)) { - return this.write(buffer); + pub fn writeLatin1(this: *StreamBuffer, buffer: []const u8, comptime check_ascii: bool) OOM!void { + if (comptime check_ascii) { + if (bun.strings.isAllASCII(buffer)) { + return this.write(buffer); + } } var byte_list = bun.ByteList.fromList(this.list); @@ -1120,14 +1159,14 @@ pub const StreamBuffer = struct { _ = try byte_list.writeLatin1(this.list.allocator, buffer); } - pub fn writeUTF16(this: *StreamBuffer, buffer: []const u16) !void { + pub fn writeUTF16(this: *StreamBuffer, buffer: []const u16) OOM!void { var byte_list = bun.ByteList.fromList(this.list); defer this.list = byte_list.listManaged(this.list.allocator); _ = try byte_list.writeUTF16(this.list.allocator, buffer); } - pub fn slice(this: *StreamBuffer) []const u8 { + pub fn slice(this: *const StreamBuffer) []const u8 { return this.list.items[this.cursor..]; } @@ -1366,7 +1405,10 @@ pub fn WindowsStreamingWriter( } const had_buffered_data = this.outgoing.isNotEmpty(); - writeFn(&this.outgoing, buffer) catch { + (if (comptime @TypeOf(writeFn) == @TypeOf(&StreamBuffer.writeLatin1) and writeFn == &StreamBuffer.writeLatin1) + writeFn(&this.outgoing, buffer, true) + else + writeFn(&this.outgoing, buffer)) catch { return .{ .err = bun.sys.Error.oom }; }; if (had_buffered_data) { diff --git a/src/io/io.zig b/src/io/io.zig index 7a4f36d3c2505b..2353a33b265c78 100644 --- a/src/io/io.zig +++ b/src/io/io.zig @@ -19,8 +19,8 @@ pub const Loop = struct { epoll_fd: if (Environment.isLinux) bun.FileDescriptor else u0 = if (Environment.isLinux) .zero else 0, cached_now: posix.timespec = .{ - .tv_nsec = 0, - .tv_sec = 0, + .nsec = 0, + .sec = 0, }, active: usize = 0, @@ -291,20 +291,20 @@ pub const Loop = struct { updateTimespec(&this.cached_now); } - extern "C" fn clock_gettime_monotonic(sec: *i64, nsec: *i64) c_int; + extern "c" fn clock_gettime_monotonic(sec: *i64, nsec: *i64) c_int; pub fn updateTimespec(timespec: *posix.timespec) void { if (comptime Environment.isLinux) { const rc = linux.clock_gettime(linux.CLOCK.MONOTONIC, timespec); assert(rc == 0); } else if (comptime Environment.isWindows) { - var tv_sec: i64 = 0; - var tv_nsec: i64 = 0; + var sec: i64 = 0; + var nsec: i64 = 0; - const rc = clock_gettime_monotonic(&tv_sec, &tv_nsec); + const rc = clock_gettime_monotonic(&sec, &nsec); assert(rc == 0); - timespec.tv_sec = @intCast(tv_sec); - timespec.tv_nsec = @intCast(tv_nsec); + timespec.sec = @intCast(sec); + timespec.nsec = @intCast(nsec); } else { std.posix.clock_gettime(std.posix.CLOCK.MONOTONIC, timespec) catch {}; } @@ -397,7 +397,7 @@ pub const Poll = struct { const GenerationNumberInt = if (Environment.isMac and Environment.allow_assert) u64 else u0; - var generation_number: GenerationNumberInt = 0; + var generation_number_monotonic: GenerationNumberInt = 0; pub const Tag = Pollable.Tag; @@ -446,24 +446,24 @@ pub const Poll = struct { pub fn fromKQueueEvent(kqueue_event: std.posix.system.kevent64_s) Flags.Set { var flags = Flags.Set{}; - if (kqueue_event.filter == std.posix.system.EVFILT_READ) { + if (kqueue_event.filter == std.posix.system.EVFILT.READ) { flags.insert(Flags.readable); log("readable", .{}); if (kqueue_event.flags & std.posix.system.EV_EOF != 0) { flags.insert(Flags.hup); log("hup", .{}); } - } else if (kqueue_event.filter == std.posix.system.EVFILT_WRITE) { + } else if (kqueue_event.filter == std.posix.system.EVFILT.WRITE) { flags.insert(Flags.writable); log("writable", .{}); if (kqueue_event.flags & std.posix.system.EV_EOF != 0) { flags.insert(Flags.hup); log("hup", .{}); } - } else if (kqueue_event.filter == std.posix.system.EVFILT_PROC) { + } else if (kqueue_event.filter == std.posix.system.EVFILT.PROC) { log("proc", .{}); flags.insert(Flags.process); - } else if (kqueue_event.filter == std.posix.system.EVFILT_MACHPORT) { + } else if (kqueue_event.filter == std.posix.system.EVFILT.MACHPORT) { log("machport", .{}); flags.insert(Flags.machport); } @@ -492,7 +492,7 @@ pub const Poll = struct { } pub fn applyKQueue( - comptime action: @Type(.EnumLiteral), + comptime action: @Type(.enum_literal), tag: Pollable.Tag, poll: *Poll, fd: bun.FileDescriptor, @@ -516,47 +516,47 @@ pub const Poll = struct { } if (comptime Environment.allow_assert and action != .cancel) { - generation_number += 1; - poll.generation_number = generation_number; + generation_number_monotonic += 1; + poll.generation_number = generation_number_monotonic; } } - const one_shot_flag = std.posix.system.EV_ONESHOT; + const one_shot_flag = std.posix.system.EV.ONESHOT; kqueue_event.* = switch (comptime action) { .readable => .{ .ident = @as(u64, @intCast(fd.int())), - .filter = std.posix.system.EVFILT_READ, + .filter = std.posix.system.EVFILT.READ, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(tag, poll).ptr()), - .flags = std.c.EV_ADD | one_shot_flag, - .ext = .{ generation_number, 0 }, + .flags = std.c.EV.ADD | one_shot_flag, + .ext = .{ generation_number_monotonic, 0 }, }, .writable => .{ .ident = @as(u64, @intCast(fd.int())), - .filter = std.posix.system.EVFILT_WRITE, + .filter = std.posix.system.EVFILT.WRITE, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(tag, poll).ptr()), - .flags = std.c.EV_ADD | one_shot_flag, - .ext = .{ generation_number, 0 }, + .flags = std.c.EV.ADD | one_shot_flag, + .ext = .{ generation_number_monotonic, 0 }, }, .cancel => if (poll.flags.contains(.poll_readable)) .{ .ident = @as(u64, @intCast(fd.int())), - .filter = std.posix.system.EVFILT_READ, + .filter = std.posix.system.EVFILT.READ, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(tag, poll).ptr()), - .flags = std.c.EV_DELETE, + .flags = std.c.EV.DELETE, .ext = .{ poll.generation_number, 0 }, } else if (poll.flags.contains(.poll_writable)) .{ .ident = @as(u64, @intCast(fd.int())), - .filter = std.posix.system.EVFILT_WRITE, + .filter = std.posix.system.EVFILT.WRITE, .data = 0, .fflags = 0, .udata = @intFromPtr(Pollable.init(tag, poll).ptr()), - .flags = std.c.EV_DELETE, + .flags = std.c.EV.DELETE, .ext = .{ poll.generation_number, 0 }, } else unreachable, @@ -578,7 +578,7 @@ pub const Poll = struct { pub fn onUpdateKQueue( event: std.posix.system.kevent64_s, ) void { - if (event.filter == std.c.EVFILT_MACHPORT) + if (event.filter == std.c.EVFILT.MACHPORT) return; const pollable = Pollable.from(event.udata); @@ -590,7 +590,7 @@ pub const Poll = struct { inline else => |t| { var this: *Pollable.Tag.Type(t) = @alignCast(@fieldParentPtr("io_poll", poll)); - if (event.flags == std.c.EV_ERROR) { + if (event.flags == std.c.EV.ERROR) { log("error({d}) = {d}", .{ event.ident, event.data }); this.onIOError(bun.sys.Error.fromCode(@enumFromInt(event.data), .kevent)); } else { diff --git a/src/js/builtins.d.ts b/src/js/builtins.d.ts index 5405daea909a72..d964b53a98c9db 100644 --- a/src/js/builtins.d.ts +++ b/src/js/builtins.d.ts @@ -363,7 +363,6 @@ declare function $isAbortSignal(signal: unknown): signal is AbortSignal; declare function $isAbsolute(): TODO; declare function $isDisturbed(): TODO; declare function $isPaused(): TODO; -declare function $isWindows(): TODO; declare function $join(): TODO; declare function $kind(): TODO; declare function $lazyStreamPrototypeMap(): TODO; @@ -582,7 +581,11 @@ interface String { } declare var $Buffer: { - new (a: any, b?: any, c?: any): Buffer; + new (array: Array): Buffer; + new (arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + new (buffer: Buffer): Buffer; + new (size: number): Buffer; + new (string: string, encoding?: BufferEncoding): Buffer; }; declare interface Error { diff --git a/src/js/builtins/BunBuiltinNames.h b/src/js/builtins/BunBuiltinNames.h index 4042228b63de20..15a65c11c3a338 100644 --- a/src/js/builtins/BunBuiltinNames.h +++ b/src/js/builtins/BunBuiltinNames.h @@ -261,6 +261,11 @@ using namespace JSC; macro(napiWrappedContents) \ macro(fastPath) \ macro(SQL) \ + macro(atimeMs) \ + macro(mtimeMs) \ + macro(ctimeMs) \ + macro(birthtimeMs) \ + macro(mode) \ BUN_ADDITIONAL_BUILTIN_NAMES(macro) // --- END of BUN_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME --- diff --git a/src/js/builtins/ProcessObjectInternals.ts b/src/js/builtins/ProcessObjectInternals.ts index 878917fc434431..70a9791d6b9c52 100644 --- a/src/js/builtins/ProcessObjectInternals.ts +++ b/src/js/builtins/ProcessObjectInternals.ts @@ -24,12 +24,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -export function getStdioWriteStream(fd) { +const enum BunProcessStdinFdType { + file = 0, + pipe = 1, + socket = 2, +} + +export function getStdioWriteStream(fd, isTTY: boolean, fdType: BunProcessStdinFdType) { $assert(typeof fd === "number", `Expected fd to be a number, got ${typeof fd}`); - const tty = require("node:tty"); let stream; - if (tty.isatty(fd)) { + if (isTTY) { + const tty = require("node:tty"); stream = new tty.WriteStream(fd); // TODO: this is the wrong place for this property. // but the TTY is technically duplex @@ -68,30 +74,25 @@ export function getStdioWriteStream(fd) { return [stream, underlyingSink]; } -export function getStdinStream(fd) { +export function getStdinStream(fd, isTTY: boolean, fdType: BunProcessStdinFdType) { const native = Bun.stdin.stream(); + // @ts-expect-error + const source = native.$bunNativePtr; var reader: ReadableStreamDefaultReader | undefined; - var readerRef; var shouldUnref = false; function ref() { $debug("ref();", reader ? "already has reader" : "getting reader"); reader ??= native.getReader(); - // TODO: remove this. likely we are dereferencing the stream - // when there is still more data to be read. - readerRef ??= setInterval(() => {}, 1 << 30); + source.updateRef(true); shouldUnref = false; } function unref() { $debug("unref();"); - if (readerRef) { - clearInterval(readerRef); - readerRef = undefined; - $debug("cleared timeout"); - } + if (reader) { try { reader.releaseLock(); @@ -120,12 +121,13 @@ export function getStdinStream(fd) { } } } + } else if (source) { + source.updateRef(false); } } - const tty = require("node:tty"); - const ReadStream = tty.isatty(fd) ? tty.ReadStream : require("node:fs").ReadStream; - const stream = new ReadStream(null, { fd }); + const ReadStream = isTTY ? require("node:tty").ReadStream : require("node:fs").ReadStream; + const stream = new ReadStream(null, { fd, autoClose: false }); const originalOn = stream.on; @@ -149,6 +151,20 @@ export function getStdinStream(fd) { stream.fd = fd; + // tty.ReadStream is supposed to extend from net.Socket. + // 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(); + return this; + }; + + stream.unref = function () { + unref(); + return this; + }; + } + const originalPause = stream.pause; stream.pause = function () { $debug("pause();"); @@ -246,7 +262,6 @@ export function getStdinStream(fd) { return stream; } - export function initializeNextTickQueue(process, nextTickQueue, drainMicrotasksFn, reportUncaughtExceptionFn) { var queue; var process; diff --git a/src/js/bun/sql.ts b/src/js/bun/sql.ts index bf5604104d7542..bcfa7865ed3f6f 100644 --- a/src/js/bun/sql.ts +++ b/src/js/bun/sql.ts @@ -92,6 +92,7 @@ enum SQLQueryFlags { unsafe = 1 << 1, bigint = 1 << 2, } + function getQueryHandle(query) { let handle = query[_handle]; if (!handle) { @@ -145,21 +146,27 @@ class Query extends PublicPromise { this[_flags] = allowUnsafeTransaction; } - async [_run]() { + async [_run](async: boolean) { const { [_handler]: handler, [_queryStatus]: status } = this; if (status & (QueryStatus.executed | QueryStatus.error | QueryStatus.cancelled | QueryStatus.invalidHandle)) { return; } + this[_queryStatus] |= QueryStatus.executed; const handle = getQueryHandle(this); if (!handle) return this; - this[_queryStatus] |= QueryStatus.executed; - // this avoids a infinite loop - await 1; + if (async) { + await 1; + } - return handler(this, handle); + try { + return handler(this, handle); + } catch (err) { + this[_queryStatus] |= QueryStatus.error; + this.reject(err); + } } get active() { @@ -219,7 +226,7 @@ class Query extends PublicPromise { } execute() { - this[_run](); + this[_run](false); return this; } @@ -238,21 +245,21 @@ class Query extends PublicPromise { } then() { - this[_run](); + this[_run](true); const result = super.$then.$apply(this, arguments); $markPromiseAsHandled(result); return result; } catch() { - this[_run](); + this[_run](true); const result = super.catch.$apply(this, arguments); $markPromiseAsHandled(result); return result; } finally() { - this[_run](); + this[_run](true); return super.finally.$apply(this, arguments); } } @@ -402,11 +409,7 @@ class PooledConnection { this.storedError = null; this.state = PooledConnectionState.pending; // retry connection - this.connection = createConnection( - this.connectionInfo, - this.#onConnected.bind(this, this.connectionInfo), - this.#onClose.bind(this, this.connectionInfo), - ); + this.connection = createConnection(this.connectionInfo, this.#onConnected.bind(this), this.#onClose.bind(this)); } close() { try { @@ -444,9 +447,9 @@ class PooledConnection { default: // we can retry this.#doRetry(); - return true; } } + return true; } } class ConnectionPool { @@ -783,9 +786,9 @@ class ConnectionPool { } else { this.waitingQueue.push(onConnected); } - } else { + } else if (!retry_in_progress) { // impossible to connect or retry - onConnected(storedError, null); + onConnected(storedError ?? connectionClosedError(), null); } return; } @@ -1298,6 +1301,7 @@ function SQL(o, e = {}) { pool.release(pooledConnection); // release the connection back to the pool return query.reject($ERR_POSTGRES_QUERY_CANCELLED("Query cancelled")); } + // bind close event to the query (will unbind and auto release the connection when the query is finished) pooledConnection.bindQuery(query, onQueryDisconnected.bind(query)); handle.run(pooledConnection.connection, query); @@ -1906,7 +1910,7 @@ function SQL(o, e = {}) { // mssql dont have release savepoint await run_internal_transaction_sql(`${RELEASE_SAVEPOINT_COMMAND} ${save_point_name}`); } - if (Array.isArray(result)) { + if ($isArray(result)) { result = await Promise.all(result); } return result; @@ -1952,7 +1956,7 @@ function SQL(o, e = {}) { await run_internal_transaction_sql(BEGIN_COMMAND); needs_rollback = true; let transaction_result = await callback(transaction_sql); - if (Array.isArray(transaction_result)) { + if ($isArray(transaction_result)) { transaction_result = await Promise.all(transaction_result); } // at this point we dont need to rollback anymore diff --git a/src/js/internal/fs/glob.ts b/src/js/internal/fs/glob.ts new file mode 100644 index 00000000000000..294313fcbc3046 --- /dev/null +++ b/src/js/internal/fs/glob.ts @@ -0,0 +1,75 @@ +import type { GlobScanOptions } from "bun"; +const { validateObject, validateString, validateFunction } = require("internal/validators"); + +const isWindows = process.platform === "win32"; + +interface GlobOptions { + /** @default process.cwd() */ + cwd?: string; + exclude?: (ent: string) => boolean; + /** + * Should glob return paths as {@link Dirent} objects. `false` for strings. + * @default false */ + withFileTypes?: boolean; +} + +interface ExtendedGlobOptions extends GlobScanOptions { + exclude(ent: string): boolean; +} + +async function* glob(pattern: string | string[], options: GlobOptions): AsyncGenerator { + pattern = validatePattern(pattern); + const globOptions = mapOptions(options); + let it = new Bun.Glob(pattern).scan(globOptions); + const exclude = globOptions.exclude; + + for await (const ent of it) { + if (exclude(ent)) continue; + yield ent; + } +} + +function* globSync(pattern: string | string[], options: GlobOptions): Generator { + pattern = validatePattern(pattern); + const globOptions = mapOptions(options); + const g = new Bun.Glob(pattern); + const exclude = globOptions.exclude; + for (const ent of g.scanSync(globOptions)) { + if (exclude(ent)) continue; + yield ent; + } +} + +function validatePattern(pattern: string | string[]): string { + if ($isArray(pattern)) { + throw new TypeError("fs.glob does not support arrays of patterns yet. Please open an issue on GitHub."); + } + validateString(pattern, "pattern"); + return isWindows ? pattern.replaceAll("/", "\\") : pattern; +} + +function mapOptions(options: GlobOptions): ExtendedGlobOptions { + validateObject(options, "options"); + + const exclude = options.exclude ?? no; + validateFunction(exclude, "options.exclude"); + + if (options.withFileTypes) { + throw new TypeError("fs.glob does not support options.withFileTypes yet. Please open an issue on GitHub."); + } + + return { + // NOTE: this is subtly different from Glob's default behavior. + // `process.cwd()` may be overridden by JS code, but native code will used the + // cached `getcwd` on BunProcess. + cwd: options?.cwd ?? process.cwd(), + // https://github.com/nodejs/node/blob/a9546024975d0bfb0a8ae47da323b10fb5cbb88b/lib/internal/fs/glob.js#L655 + followSymlinks: true, + exclude, + }; +} + +// `var` avoids TDZ checks. +var no = _ => false; + +export default { glob, globSync }; diff --git a/src/js/internal/fs/streams.ts b/src/js/internal/fs/streams.ts index 8818fc3562d68d..e110f5057a121e 100644 --- a/src/js/internal/fs/streams.ts +++ b/src/js/internal/fs/streams.ts @@ -47,8 +47,6 @@ const kWriteFastSimpleBuffering = Symbol("writeFastSimpleBuffering"); // using `node:fs`, `Bun.file(...).writer()` is used instead. const kWriteStreamFastPath = Symbol("kWriteStreamFastPath"); const kFs = Symbol("kFs"); -const kIoDone = Symbol("kIoDone"); -const kIsPerformingIO = Symbol("kIsPerformingIO"); const { read: fileHandlePrototypeRead, @@ -208,7 +206,6 @@ function ReadStream(this: FSStream, path, options): void { throw $ERR_OUT_OF_RANGE("start", `<= "end" (here: ${end})`, start); } } - this[kIsPerformingIO] = false; this[kReadStreamFastPath] = start === 0 && @@ -265,26 +262,26 @@ function streamConstruct(this: FSStream, callback: (e?: any) => void) { } as any; this.open(); } else { - if (fastPath) - fast: { - // // there is a chance that this fd is not actually correct but it will be a number - // if (fastPath !== true) { - // // @ts-expect-error undocumented. to make this public please make it a - // // getter. couldn't figure that out sorry - // this.fd = fastPath._getFd(); - // } else { - // if (fs.open !== open || fs.write !== write || fs.fsync !== fsync || fs.close !== close) { - // this[kWriteStreamFastPath] = undefined; - // break fast; - // } - // // @ts-expect-error - // this.fd = (this[kWriteStreamFastPath] = Bun.file(this.path).writer())._getFd(); - // } - callback(); - this.emit("open", this.fd); - this.emit("ready"); - return; - } + if (fastPath) { + // // there is a chance that this fd is not actually correct but it will be a number + // if (fastPath !== true) { + // // @ts-expect-error undocumented. to make this public please make it a + // // getter. couldn't figure that out sorry + // this.fd = fastPath._getFd(); + // } else { + // if (fs.open !== open || fs.write !== write || fs.fsync !== fsync || fs.close !== close) { + // this[kWriteStreamFastPath] = undefined; + // break fast; + // } + // // @ts-expect-error + // this.fd = (this[kWriteStreamFastPath] = Bun.file(this.path).writer())._getFd(); + // } + callback(); + this.emit("open", this.fd); + this.emit("ready"); + return; + } + this[kFs].open(this.path, this.flags, this.mode, (err, fd) => { if (err) { callback(err); @@ -312,16 +309,7 @@ readStreamPrototype._read = function (n) { const buf = Buffer.allocUnsafeSlow(n); - this[kIsPerformingIO] = true; this[kFs].read(this.fd, buf, 0, n, this.pos, (er, bytesRead, buf) => { - this[kIsPerformingIO] = false; - - // Tell ._destroy() that it's safe to close the fd now. - if (this.destroyed) { - this.emit(kIoDone, er); - return; - } - if (er) { require("internal/streams/destroy").errorOrDestroy(this, er); } else if (bytesRead > 0) { @@ -354,8 +342,8 @@ readStreamPrototype._destroy = function (this: FSStream, err, cb) { // running in a thread pool. Therefore, file descriptors are not safe // to close while used in a pending read or write operation. Wait for // any pending IO (kIsPerformingIO) to complete (kIoDone). - if (this[kIsPerformingIO]) { - this.once(kIoDone, er => close(this, err || er, cb)); + if (this[kReadStreamFastPath]) { + this.once(kReadStreamFastPath, er => close(this, err || er, cb)); } else { close(this, err, cb); } @@ -570,19 +558,34 @@ function writevAll(chunks, size, pos, cb, retries = 0) { } function _write(data, encoding, cb) { - this[kIsPerformingIO] = true; - writeAll.$call(this, data, data.length, this.pos, er => { - this[kIsPerformingIO] = false; - if (this.destroyed) { - // Tell ._destroy() that it's safe to close the fd now. - cb(er); - return this.emit(kIoDone, er); - } + const fileSink = this[kWriteStreamFastPath]; - cb(er); - }); + if (fileSink && fileSink !== true) { + const maybePromise = fileSink.write(data); + if ($isPromise(maybePromise)) { + maybePromise + .then(() => { + this.emit("drain"); // Emit drain event + cb(null); + }) + .catch(cb); + return false; // Indicate backpressure + } else { + cb(null); + return true; // No backpressure + } + } else { + writeAll.$call(this, data, data.length, this.pos, er => { + if (this.destroyed) { + cb(er); + return; + } + cb(er); + }); - if (this.pos !== undefined) this.pos += data.length; + if (this.pos !== undefined) this.pos += data.length; + // Don't return anything for legacy path - matches Node.js behavior + } } writeStreamPrototype._write = _write; @@ -594,12 +597,6 @@ function underscoreWriteFast(this: FSStream, data: any, encoding: any, cb: any) return this._write(data, encoding, cb); } try { - if (this[kIsPerformingIO] > 0) { - this.once(kIoDone, () => { - underscoreWriteFast.$call(this, data, encoding, cb); - }); - return; - } if (fileSink === true) { fileSink = this[kWriteStreamFastPath] = Bun.file(this.path).writer(); // @ts-expect-error @@ -607,23 +604,16 @@ function underscoreWriteFast(this: FSStream, data: any, encoding: any, cb: any) } const maybePromise = fileSink.write(data); - if ( - $isPromise(maybePromise) && - ($getPromiseInternalField(maybePromise, $promiseFieldFlags) & $promiseStateMask) === $promiseStatePending - ) { - const prevRefCount = this[kIsPerformingIO]; - this[kIsPerformingIO] = (prevRefCount === true ? 0 : prevRefCount || 0) + 1; - if (cb) - maybePromise.then(() => { - cb(null); - this[kIsPerformingIO] -= 1; - this.emit(kIoDone, null); - }, cb); + if ($isPromise(maybePromise)) { + maybePromise.then(() => { + cb(null); + this.emit("drain"); + }, cb); return false; } else { if (cb) process.nextTick(cb, null); + return true; } - return true; } catch (e) { if (cb) process.nextTick(cb, e); return false; @@ -643,14 +633,31 @@ function writeFast(this: FSStream, data: any, encoding: any, cb: any) { if (typeof cb !== "function") { cb = streamNoop; } - const result: any = this._write(data, encoding, cb); - if (this.write === writeFast) { - this.write = writablePrototypeWrite; + + const fileSink = this[kWriteStreamFastPath]; + if (fileSink && fileSink !== true) { + const maybePromise = fileSink.write(data); + if ($isPromise(maybePromise)) { + maybePromise + .then(() => { + this.emit("drain"); // Emit drain event + cb(null); + }) + .catch(cb); + return false; // Indicate backpressure + } else { + cb(null); + return true; // No backpressure + } } else { - // test-console-group.js - this[kWriteMonkeyPatchDefense] = true; + const result: any = this._write(data, encoding, cb); + if (this.write === writeFast) { + this.write = writablePrototypeWrite; + } else { + this[kWriteMonkeyPatchDefense] = true; + } + return result; } - return result; } writeStreamPrototype._writev = function (data, cb) { @@ -660,40 +667,49 @@ writeStreamPrototype._writev = function (data, cb) { for (let i = 0; i < len; i++) { const chunk = data[i].chunk; - chunks[i] = chunk; size += chunk.length; } - this[kIsPerformingIO] = true; - writevAll.$call(this, chunks, size, this.pos, er => { - this[kIsPerformingIO] = false; - if (this.destroyed) { - // Tell ._destroy() that it's safe to close the fd now. - cb(er); - return this.emit(kIoDone, er); + const fileSink = this[kWriteStreamFastPath]; + if (fileSink && fileSink !== true) { + const maybePromise = fileSink.write(Buffer.concat(chunks)); + if ($isPromise(maybePromise)) { + maybePromise + .then(() => { + this.emit("drain"); + cb(null); + }) + .catch(cb); + return false; + } else { + cb(null); + return true; } + } else { + writevAll.$call(this, chunks, size, this.pos, er => { + if (this.destroyed) { + cb(er); + return; + } + cb(er); + }); - cb(er); - }); - - if (this.pos !== undefined) this.pos += size; + if (this.pos !== undefined) this.pos += size; + // Don't return anything for legacy path - matches Node.js behavior + } }; writeStreamPrototype._destroy = function (err, cb) { - // Usually for async IO it is safe to close a file descriptor - // even when there are pending operations. However, due to platform - // differences file IO is implemented using synchronous operations - // running in a thread pool. Therefore, file descriptors are not safe - // to close while used in a pending read or write operation. Wait for - // any pending IO (kIsPerformingIO) to complete (kIoDone). - if (this[kIsPerformingIO] > 0) { - this.once(kIoDone, er => { - close(this, err || er, cb); - }); - } else { - close(this, err, cb); + const sink = this[kWriteStreamFastPath]; + if (sink && sink !== true) { + const end = sink.end(err); + if ($isPromise(end)) { + end.then(() => cb(err), cb); + return; + } } + close(this, err, cb); }; writeStreamPrototype.close = function (this: FSStream, cb) { @@ -728,7 +744,7 @@ Object.defineProperty(writeStreamPrototype, "autoClose", { }, }); -Object.$defineProperty(writeStreamPrototype, "pending", { +Object.defineProperty(writeStreamPrototype, "pending", { get() { return this.fd === null; }, diff --git a/src/js/internal/html.ts b/src/js/internal/html.ts new file mode 100644 index 00000000000000..d1f2f9cf67ef29 --- /dev/null +++ b/src/js/internal/html.ts @@ -0,0 +1,354 @@ +// This is the file that loads when you pass a '.html' entry point to Bun. +// It imports the entry points and initializes a server. +import type { HTMLBundle, Server } from "bun"; +const initial = performance.now(); +const argv = process.argv; + +// `import` cannot be used in this file and only Bun builtin modules can be used. +const path = require("node:path"); + +const env = Bun.env; + +// This function is called at startup. +async function start() { + let args: string[] = []; + const cwd = process.cwd(); + let hostname = "localhost"; + let port: number | undefined = undefined; + + // Step 1. Resolve all HTML entry points + for (let i = 1, argvLength = argv.length; i < argvLength; i++) { + const arg = argv[i]; + + if (!arg.endsWith(".html")) { + if (arg.startsWith("--hostname=")) { + hostname = arg.slice("--hostname=".length); + if (hostname.includes(":")) { + const [host, portString] = hostname.split(":"); + hostname = host; + port = parseInt(portString, 10); + } + } else if (arg.startsWith("--port=")) { + port = parseInt(arg.slice("--port=".length), 10); + } else if (arg.startsWith("--host=")) { + hostname = arg.slice("--host=".length); + if (hostname.includes(":")) { + const [host, portString] = hostname.split(":"); + hostname = host; + port = parseInt(portString, 10); + } + } + + if (arg === "--help") { + console.log(` +Bun v${Bun.version} (html) + +Usage: + bun [...html-files] [options] + +Options: + + --port= + --host=, --hostname= + +Examples: + + bun index.html + bun ./index.html ./about.html --port=3000 + bun index.html --host=localhost:3000 + bun index.html --hostname=localhost:3000 + bun ./*.html + +This is a small wrapper around Bun.serve() that automatically serves the HTML files you pass in without +having to manually call Bun.serve() or write the boilerplate yourself. This runs Bun's bundler on +the HTML files, their JavaScript, and CSS, and serves them up. This doesn't do anything you can't do +yourself with Bun.serve(). +`); + process.exit(0); + } + + continue; + } + + if (arg.includes("*") || arg.includes("**") || arg.includes("{")) { + const glob = new Bun.Glob(arg); + + for (const file of glob.scanSync(cwd)) { + let resolved = path.resolve(cwd, file); + try { + resolved = Bun.resolveSync(resolved, cwd); + } catch { + resolved = Bun.resolveSync("./" + resolved, cwd); + } + + args.push(resolved); + } + } else { + let resolved = arg; + try { + resolved = Bun.resolveSync(arg, cwd); + } catch { + resolved = Bun.resolveSync("./" + arg, cwd); + } + + args.push(resolved); + } + + if (args.length > 1) { + args = [...new Set(args)]; + } + } + + if (args.length === 0) { + throw new Error("No HTML files found matching " + JSON.stringify(Bun.main)); + } + + // Add cwd to find longest common path + let needsPop = false; + if (args.length === 1) { + args.push(process.cwd()); + needsPop = true; + } + + // Find longest common path prefix to use as the base path when there are + // multiple entry points + let longestCommonPath = args.reduce((acc, curr) => { + if (!acc) return curr; + let i = 0; + while (i < acc.length && i < curr.length && acc[i] === curr[i]) i++; + return acc.slice(0, i); + }); + + if (path.platform === "win32") { + longestCommonPath = longestCommonPath.replaceAll("\\", "/"); + } + + if (needsPop) { + // Remove cwd from args + args.pop(); + } + + // Transform file paths into friendly URL paths + // - "index.html" -> "/" + // - "about/index.html" -> "/about" + // - "about/foo.html" -> "/about/foo" + // - "foo.html" -> "/foo" + const servePaths = args.map(arg => { + if (process.platform === "win32") { + arg = arg.replaceAll("\\", "/"); + } + const basename = path.basename(arg); + const isIndexHtml = basename === "index.html"; + + let servePath = arg; + if (servePath.startsWith(longestCommonPath)) { + servePath = servePath.slice(longestCommonPath.length); + } else { + const relative = path.relative(longestCommonPath, servePath); + if (!relative.startsWith("..")) { + servePath = relative; + } + } + + if (isIndexHtml && servePath.length === 0) { + servePath = "/"; + } else if (isIndexHtml) { + servePath = servePath.slice(0, -"index.html".length); + } + + if (servePath.endsWith(".html")) { + servePath = servePath.slice(0, -".html".length); + } + + if (servePath.endsWith("/")) { + servePath = servePath.slice(0, -1); + } + + if (servePath.startsWith("/")) { + servePath = servePath.slice(1); + } + + if (servePath === "/") servePath = ""; + + return servePath; + }); + + const htmlImports = await Promise.all( + args.map(arg => { + return import(arg).then(m => m.default); + }), + ); + + // If you're only providing one entry point, then match everything to it. + // (except for assets, which have higher precedence) + if (htmlImports.length === 1 && servePaths[0] === "") { + servePaths[0] = "*"; + } + + const staticRoutes = htmlImports.reduce( + (acc, htmlImport, index) => { + const html = htmlImport; + const servePath = servePaths[index]; + + acc["/" + servePath] = html; + return acc; + }, + {} as Record, + ); + var server: Server; + getServer: { + try { + server = Bun.serve({ + static: staticRoutes, + development: env.NODE_ENV !== "production", + + hostname, + port, + + // use the default port via existing port detection code. + // port: 3000, + + fetch(req: Request) { + return new Response("Not found", { status: 404 }); + }, + }); + break getServer; + } catch (error: any) { + if (error?.code === "EADDRINUSE") { + let defaultPort = port || parseInt(env.PORT || env.BUN_PORT || env.NODE_PORT || "3000", 10); + for (let remainingTries = 5; remainingTries > 0; remainingTries--) { + try { + server = Bun.serve({ + static: staticRoutes, + development: env.NODE_ENV !== "production", + + hostname, + + // Retry with a different port up to 4 times. + port: defaultPort++, + + fetch(req: Request) { + return new Response("Not found", { status: 404 }); + }, + }); + break getServer; + } catch (error: any) { + if (error?.code === "EADDRINUSE") { + continue; + } + throw error; + } + } + } + + throw error; + } + } + const elapsed = (performance.now() - initial).toFixed(2); + const enableANSIColors = Bun.enableANSIColors; + function printInitialMessage(isFirst: boolean) { + if (enableANSIColors) { + let topLine = `${server.development ? "\x1b[34;7m DEV \x1b[0m " : ""}\x1b[1;34m\x1b[5mBun\x1b[0m \x1b[1;34mv${Bun.version}\x1b[0m`; + if (isFirst) { + topLine += ` \x1b[2mready in\x1b[0m \x1b[1m${elapsed}\x1b[0m ms`; + } + console.log(topLine + "\n"); + console.log(`\x1b[1;34m➜\x1b[0m \x1b[36m${server!.url.href}\x1b[0m`); + } else { + let topLine = `Bun v${Bun.version}`; + if (isFirst) { + if (server.development) { + topLine += " dev server"; + } + topLine += ` ready in ${elapsed} ms`; + } + console.log(topLine + "\n"); + console.log(`url: ${server!.url.href}`); + } + if (htmlImports.length > 1 || (servePaths[0] !== "" && servePaths[0] !== "*")) { + console.log("\nRoutes:"); + + const pairs: { route: string; importPath: string }[] = []; + + for (let i = 0, length = servePaths.length; i < length; i++) { + const route = servePaths[i]; + const importPath = args[i]; + pairs.push({ route, importPath }); + } + pairs.sort((a, b) => { + if (b.route === "") return 1; + if (a.route === "") return -1; + return a.route.localeCompare(b.route); + }); + for (let i = 0, length = pairs.length; i < length; i++) { + const { route, importPath } = pairs[i]; + const isLast = i === length - 1; + const prefix = isLast ? " └── " : " ├── "; + if (enableANSIColors) { + console.log(`${prefix}\x1b[36m/${route}\x1b[0m \x1b[2m→ ${path.relative(process.cwd(), importPath)}\x1b[0m`); + } else { + console.log(`${prefix}/${route} → ${path.relative(process.cwd(), importPath)}`); + } + } + } + + if (isFirst && process.stdin.isTTY) { + if (enableANSIColors) { + console.log(); + console.log("\x1b[2mPress \x1b[2;36mh + Enter\x1b[39;2m to show shortcuts\x1b[0m"); + } else { + console.log(); + console.log("Press h + Enter to show shortcuts"); + } + } + } + + printInitialMessage(true); + + // Keyboard shortcuts + if (process.stdin.isTTY) { + // Handle Ctrl+C and other termination signals + process.on("SIGINT", () => process.exit()); + process.on("SIGHUP", () => process.exit()); + process.on("SIGTERM", () => process.exit()); + process.stdin.on("data", data => { + const key = data.toString().toLowerCase().replaceAll("\r\n", "\n"); + + switch (key) { + case "\x03": // Ctrl+C + case "q\n": + process.exit(); + break; + + case "c\n": + console.clear(); + printInitialMessage(false); + break; + + case "o\n": + const url = server.url.toString(); + + if (process.platform === "darwin") { + // TODO: copy the AppleScript from create-react-app or Vite. + Bun.spawn(["open", url]).exited.catch(() => {}); + } else if (process.platform === "win32") { + Bun.spawn(["start", url]).exited.catch(() => {}); + } else { + Bun.spawn(["xdg-open", url]).exited.catch(() => {}); + } + break; + + case "h\n": + console.clear(); + printInitialMessage(false); + console.log("\n Shortcuts\x1b[2m:\x1b[0m\n"); + console.log(" \x1b[2m→\x1b[0m \x1b[36mc + Enter\x1b[0m clear screen"); + console.log(" \x1b[2m→\x1b[0m \x1b[36mo + Enter\x1b[0m open in browser"); + console.log(" \x1b[2m→\x1b[0m \x1b[36mq + Enter\x1b[0m quit (or Ctrl+C)\n"); + break; + } + }); + } +} + +export default start; diff --git a/src/js/internal/validators.ts b/src/js/internal/validators.ts index 2df37ba6eaae72..e06492b28e5fda 100644 --- a/src/js/internal/validators.ts +++ b/src/js/internal/validators.ts @@ -68,7 +68,7 @@ function validateLinkHeaderValue(hints) { } hideFromStack(validateLinkHeaderValue); // TODO: do it in NodeValidator.cpp -function validateObject(value, name) { +function validateObject(value: unknown, name: string): asserts value is object { if (typeof value !== "object" || value === null) throw $ERR_INVALID_ARG_TYPE(name, "object", value); } hideFromStack(validateObject); @@ -89,9 +89,22 @@ export default { validateObject: validateObject, validateLinkHeaderValue: validateLinkHeaderValue, checkIsHttpToken: checkIsHttpToken, - /** `(value, name, min = NumberMIN_SAFE_INTEGER, max = NumberMAX_SAFE_INTEGER)` */ + /** + * @param value the value that should be an int + * @paran name the name of the parameter. Used when creating error codes + * @param min minimum value, inclusive. Defaults to {@link Number.MIN_SAFE_INTEGER}. + * @param max maximum value, inclusive. Defaults to {@link Number.MAX_SAFE_INTEGER}. + * + * @throws if `value` is not an int + * @throws if `value` is outside `[min, max]` + */ validateInteger: $newCppFunction("NodeValidator.cpp", "jsFunction_validateInteger", 0), - /** `(value, name, min = undefined, max)` */ + /** + * @param value the value that should be an int + * @paran name the name of the parameter. Used when creating error codes + * @param min minimum value, exclusive. Defaults to {@link Number.MIN_SAFE_INTEGER}. + * @param max maximum value, exclusive. Defaults to {@link Number.MAX_SAFE_INTEGER}. + */ validateNumber: $newCppFunction("NodeValidator.cpp", "jsFunction_validateNumber", 0), /** `(value, name)` */ validateString: $newCppFunction("NodeValidator.cpp", "jsFunction_validateString", 0), diff --git a/src/js/node/child_process.ts b/src/js/node/child_process.ts index 58492778501342..a94dfa43b18c0b 100644 --- a/src/js/node/child_process.ts +++ b/src/js/node/child_process.ts @@ -553,7 +553,7 @@ function spawnSync(file, args, options) { } else if (typeof input === "string") { bunStdio[0] = Buffer.from(input, encoding || "utf8"); } else { - throw $ERR_INVALID_ARG_TYPE(`options.stdio[0]`, ["Buffer", "TypedArray", "DataView", "string"], input); + throw $ERR_INVALID_ARG_TYPE(`options.stdio[0]`, ["string", "Buffer", "TypedArray", "DataView"], input); } } @@ -1120,12 +1120,14 @@ class ChildProcess extends EventEmitter { } } + const handle = this.#handle; const io = this.#stdioOptions[i]; switch (i) { case 0: { switch (io) { case "pipe": { - const stdin = this.#handle.stdin; + const stdin = handle?.stdin; + if (!stdin) // This can happen if the process was already killed. return new ShimmedStdin(); @@ -1143,7 +1145,7 @@ class ChildProcess extends EventEmitter { case 1: { switch (io) { case "pipe": { - const value = this.#handle[fdToStdioName(i) as any as number]; + const value = handle?.[fdToStdioName(i as 1 | 2)!]; // This can happen if the process was already killed. if (!value) return new ShimmedStdioOutStream(); @@ -1163,7 +1165,7 @@ class ChildProcess extends EventEmitter { switch (io) { case "pipe": if (!NetModule) NetModule = require("node:net"); - const fd = this.#handle.stdio[i]; + const fd = handle && handle.stdio[i]; if (!fd) return null; return new NetModule.connect({ fd }); } @@ -1275,12 +1277,16 @@ class ChildProcess extends EventEmitter { env: env, detached: typeof detachedOption !== "undefined" ? !!detachedOption : false, onExit: (handle, exitCode, signalCode, err) => { - if (hasSocketsToEagerlyLoad) { - this.stdio; - } - $debug("ChildProcess: onExit", exitCode, signalCode, err, this.pid); this.#handle = handle; this.pid = this.#handle.pid; + $debug("ChildProcess: onExit", exitCode, signalCode, err, this.pid); + + if (hasSocketsToEagerlyLoad) { + process.nextTick(() => { + this.stdio; + $debug("ChildProcess: onExit", exitCode, signalCode, err, this.pid); + }); + } process.nextTick( (exitCode, signalCode, err) => this.#handleOnExit(exitCode, signalCode, err), @@ -1476,7 +1482,7 @@ function isNodeStreamWritable(item) { return true; } -function fdToStdioName(fd) { +function fdToStdioName(fd: number) { switch (fd) { case 0: return "stdin"; diff --git a/src/js/node/dgram.ts b/src/js/node/dgram.ts index e68678c2eab263..87192161e28af4 100644 --- a/src/js/node/dgram.ts +++ b/src/js/node/dgram.ts @@ -33,8 +33,10 @@ const SEND_BUFFER = false; const LIBUS_LISTEN_DEFAULT = 0; const LIBUS_LISTEN_EXCLUSIVE_PORT = 1; const LIBUS_SOCKET_ALLOW_HALF_OPEN = 2; -const LIBUS_SOCKET_REUSE_PORT = 4; +const LIBUS_LISTEN_REUSE_PORT = 4; const LIBUS_SOCKET_IPV6_ONLY = 8; +const LIBUS_LISTEN_REUSE_ADDR = 16; +const LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE = 32; const kStateSymbol = Symbol("state symbol"); const kOwnerSymbol = Symbol("owner symbol"); @@ -165,7 +167,7 @@ function Socket(type, listener) { bindState: BIND_STATE_UNBOUND, connectState: CONNECT_STATE_DISCONNECTED, queue: undefined, - reuseAddr: options && options.reuseAddr, // Use UV_UDP_REUSEADDR if true. + reuseAddr: options && options.reuseAddr, reusePort: options && options.reusePort, ipv6Only: options && options.ipv6Only, recvBufferSize, @@ -301,10 +303,10 @@ Socket.prototype.bind = function (port_, address_ /* , callback */) { return; } - let flags = 0; + let flags = LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE; if (state.reuseAddr) { - flags |= 0; //UV_UDP_REUSEADDR; + flags |= LIBUS_LISTEN_REUSE_ADDR; } if (state.ipv6Only) { @@ -313,9 +315,7 @@ Socket.prototype.bind = function (port_, address_ /* , callback */) { if (state.reusePort) { exclusive = true; // TODO: cluster support - flags |= LIBUS_SOCKET_REUSE_PORT; - } else { - flags |= LIBUS_LISTEN_EXCLUSIVE_PORT; + flags |= LIBUS_LISTEN_REUSE_PORT; } // TODO flags @@ -456,7 +456,7 @@ function sliceBuffer(buffer, offset, length) { if (typeof buffer === "string") { buffer = Buffer.from(buffer); } else if (!ArrayBuffer.isView(buffer)) { - throw $ERR_INVALID_ARG_TYPE("buffer", ["Buffer", "TypedArray", "DataView", "string"], buffer); + throw $ERR_INVALID_ARG_TYPE("buffer", ["string", "Buffer", "TypedArray", "DataView"], buffer); } offset = offset >>> 0; @@ -562,12 +562,12 @@ Socket.prototype.send = function (buffer, offset, length, port, address, callbac if (typeof buffer === "string") { list = [Buffer.from(buffer)]; } else if (!ArrayBuffer.isView(buffer)) { - throw $ERR_INVALID_ARG_TYPE("buffer", ["Buffer", "TypedArray", "DataView", "string"], buffer); + throw $ERR_INVALID_ARG_TYPE("buffer", ["string", "Buffer", "TypedArray", "DataView"], buffer); } else { list = [buffer]; } } else if (!(list = fixBufferList(buffer))) { - throw $ERR_INVALID_ARG_TYPE("buffer list arguments", ["Buffer", "TypedArray", "DataView", "string"], buffer); + throw $ERR_INVALID_ARG_TYPE("buffer list arguments", ["string", "Buffer", "TypedArray", "DataView"], buffer); } if (!connected) port = validatePort(port, "Port", false); @@ -627,7 +627,12 @@ function doSend(ex, self, ip, list, address, port, callback) { let err = null; let success = false; - const data = Buffer.concat(list); + let data; + if (list === undefined) data = new $Buffer(0); + else if (Array.isArray(list) && list.length === 1) { + const { buffer, byteOffset, byteLength } = list[0]; + data = new $Buffer(buffer).slice(byteOffset).slice(0, byteLength); + } else data = Buffer.concat(list); try { if (port) { success = socket.send(data, port, ip); @@ -652,7 +657,7 @@ function doSend(ex, self, ip, list, address, port, callback) { /* const req = new SendWrap(); - req.list = list; // Keep reference alive. + req.list = list; // Keep reference alive. req.address = address; req.port = port; if (callback) { @@ -661,22 +666,19 @@ function doSend(ex, self, ip, list, address, port, callback) { } let err; - if (port) - err = state.handle.send(req, list, list.length, port, ip, !!callback); - else - err = state.handle.send(req, list, list.length, !!callback); + if (port) err = state.handle.send(req, list, list.length, port, ip, !!callback); + else err = state.handle.send(req, list, list.length, !!callback); if (err >= 1) { // Synchronous finish. The return code is msg_length + 1 so that we can // distinguish between synchronous success and asynchronous success. - if (callback) - process.nextTick(callback, null, err - 1); + if (callback) process.nextTick(callback, null, err - 1); return; } if (err && callback) { // Don't emit as error, dgram_legacy.js compatibility - const ex = new ExceptionWithHostPort(err, 'send', address, port); + const ex = new ExceptionWithHostPort(err, "send", address, port); process.nextTick(callback, ex); } */ diff --git a/src/js/node/fs.promises.ts b/src/js/node/fs.promises.ts index 4ea642a6acb8e0..e3b4ab770ac1af 100644 --- a/src/js/node/fs.promises.ts +++ b/src/js/node/fs.promises.ts @@ -1,8 +1,8 @@ // Hardcoded module "node:fs/promises" -import type { Dirent } from "fs"; const types = require("node:util/types"); const EventEmitter = require("node:events"); const fs = $zig("node_fs_binding.zig", "createBinding"); +const { glob } = require("internal/fs/glob"); const constants = $processBindingConstants.fs; var PromisePrototypeFinally = Promise.prototype.finally; //TODO @@ -22,7 +22,7 @@ const kDeserialize = Symbol("kDeserialize"); const kEmptyObject = ObjectFreeze({ __proto__: null }); const kFlag = Symbol("kFlag"); -const { validateObject, validateInteger } = require("internal/validators"); +const { validateInteger } = require("internal/validators"); function watch( filename: string | Buffer | URL, @@ -112,7 +112,7 @@ function cp(src, dest, options) { } async function opendir(dir: string, options) { - return new (require('node:fs').Dir)(1, dir, options); + return new (require("node:fs").Dir)(1, dir, options); } const private_symbols = { @@ -152,6 +152,7 @@ const exports = { fdatasync: asyncWrap(fs.fdatasync, "fdatasync"), ftruncate: asyncWrap(fs.ftruncate, "ftruncate"), futimes: asyncWrap(fs.futimes, "futimes"), + glob, lchmod: asyncWrap(fs.lchmod, "lchmod"), lchown: asyncWrap(fs.lchown, "lchown"), link: asyncWrap(fs.link, "link"), diff --git a/src/js/node/fs.ts b/src/js/node/fs.ts index f3fd95a9cb6e49..f480b390a20b7c 100644 --- a/src/js/node/fs.ts +++ b/src/js/node/fs.ts @@ -1,8 +1,11 @@ // Hardcoded module "node:fs" -import type { Stats as StatsType } from "fs"; +import type { Stats as StatsType, Dirent as DirentType, PathLike } from "fs"; const EventEmitter = require("node:events"); const promises = require("node:fs/promises"); const types = require("node:util/types"); +const { validateFunction, validateInteger } = require("internal/validators"); + +const kEmptyObject = Object.freeze(Object.create(null)); const isDate = types.isDate; @@ -11,6 +14,10 @@ const isDate = types.isDate; const { fs } = promises.$data; const constants = $processBindingConstants.fs; +var _lazyGlob; +function lazyGlob() { + return (_lazyGlob ??= require("internal/fs/glob")); +} function ensureCallback(callback) { if (!$isCallable(callback)) { @@ -599,12 +606,15 @@ var access = function access(path, mode, callback) { return new FSWatcher(path, options, listener); }, opendir = function opendir(path, options, callback) { + // TODO: validatePath + // validateString(path, "path"); if (typeof options === "function") { callback = options; options = undefined; } + validateFunction(callback, "callback"); const result = new Dir(1, path, options); - if (callback) callback(null, result); + callback(null, result); }; const { defineCustomPromisifyArgs } = require("internal/promisify"); @@ -700,7 +710,7 @@ function encodeRealpathResult(result, encoding) { } let assertEncodingForWindows: any = undefined; -const realpathSync: any = +const realpathSync = process.platform !== "win32" ? fs.realpathSync.bind(fs) : function realpathSync(p, options) { @@ -1009,23 +1019,32 @@ function _toUnixTimestamp(time: any, name = "time") { } function opendirSync(path, options) { + // TODO: validatePath + // validateString(path, "path"); return new Dir(1, path, options); } class Dir { - #handle; - #path; + /** + * `-1` when closed. stdio handles (0, 1, 2) don't actually get closed by + * {@link close} or {@link closeSync}. + */ + #handle: number; + #path: PathLike; #options; - #entries: any[] | null = null; + #entries: DirentType[] | null = null; - constructor(handle, path, options) { - if (handle == null) throw $ERR_MISSING_ARGS("handle"); - this.#handle = handle; + constructor(handle, path: PathLike, options) { + if ($isUndefinedOrNull(handle)) throw $ERR_MISSING_ARGS("handle"); + validateInteger(handle, "handle", 0); + this.#handle = $toLength(handle); this.#path = path; this.#options = options; } readSync() { + if (this.#handle < 0) throw $ERR_DIR_CLOSED(); + let entries = (this.#entries ??= fs.readdirSync(this.#path, { withFileTypes: true, encoding: this.#options?.encoding, @@ -1034,8 +1053,11 @@ class Dir { return entries.shift() ?? null; } - read(cb?): any { - if (cb) { + read(cb?: (err: Error | null, entry: DirentType) => void): any { + if (this.#handle < 0) throw $ERR_DIR_CLOSED(); + + if (!$isUndefinedOrNull(cb)) { + validateFunction(cb, "callback"); return this.read().then(entry => cb(null, entry)); } @@ -1054,13 +1076,22 @@ class Dir { } close(cb?: () => void) { - if (cb) { + const handle = this.#handle; + if (handle < 0) throw $ERR_DIR_CLOSED(); + if (!$isUndefinedOrNull(cb)) { + validateFunction(cb, "callback"); process.nextTick(cb); } - return fs.closedirSync(this.#handle); + if (handle > 2) fs.closeSync(handle); + this.#handle = -1; } - closeSync() {} + closeSync() { + const handle = this.#handle; + if (handle < 0) throw $ERR_DIR_CLOSED(); + if (handle > 2) fs.closeSync(handle); + this.#handle = -1; + } get path() { return this.#path; @@ -1076,6 +1107,22 @@ class Dir { } } +function glob(pattern: string | string[], options, callback) { + if (typeof options === "function") { + callback = options; + options = undefined; + } + validateFunction(callback, "callback"); + + Array.fromAsync(lazyGlob().glob(pattern, options ?? kEmptyObject)) + .then(result => callback(null, result)) + .catch(callback); +} + +function globSync(pattern: string | string[], options): string[] { + return Array.from(lazyGlob().globSync(pattern, options ?? kEmptyObject)); +} + var exports = { appendFile, appendFileSync, @@ -1109,6 +1156,8 @@ var exports = { ftruncateSync, futimes, futimesSync, + glob, + globSync, lchown, lchownSync, lchmod, diff --git a/src/js/node/http.ts b/src/js/node/http.ts index 2068f73ecb4edf..60679acd08efba 100644 --- a/src/js/node/http.ts +++ b/src/js/node/http.ts @@ -79,7 +79,7 @@ function ERR_HTTP_SOCKET_ASSIGNED() { // TODO: add primordial for URL // Importing from node:url is unnecessary -const { URL } = globalThis; +const { URL, WebSocket, CloseEvent, MessageEvent } = globalThis; const globalReportError = globalThis.reportError; const setTimeout = globalThis.setTimeout; @@ -2384,4 +2384,7 @@ export default { globalAgent, ClientRequest, OutgoingMessage, + WebSocket, + CloseEvent, + MessageEvent, }; diff --git a/src/js/node/tty.ts b/src/js/node/tty.ts index 581c77cf061b82..5dd20bcd7349c4 100644 --- a/src/js/node/tty.ts +++ b/src/js/node/tty.ts @@ -80,7 +80,7 @@ Object.defineProperty(ReadStream, "prototype", { function WriteStream(fd): void { if (!(this instanceof WriteStream)) return new WriteStream(fd); - const stream = require("node:fs").WriteStream.$call(this, null, { fd, $fastPath: true }); + const stream = require("node:fs").WriteStream.$call(this, null, { fd, $fastPath: true, autoClose: false }); stream.columns = undefined; stream.rows = undefined; stream.isTTY = isatty(stream.fd); diff --git a/src/js/node/url.ts b/src/js/node/url.ts index bef41376f3d557..5bf493904ef606 100644 --- a/src/js/node/url.ts +++ b/src/js/node/url.ts @@ -105,23 +105,11 @@ var protocolPattern = /^([a-z0-9.+-]+:)/i, "file:": true, }; -let urlParseWarned = false; function urlParse( url: string | URL | Url, // really has unknown type but intellisense is nice parseQueryString?: boolean, slashesDenoteHost?: boolean, ) { - if (!urlParseWarned && !lazyUtil().isInsideNodeModules()) { - urlParseWarned = true; - process.emitWarning( - "`url.parse()` behavior is not standardized and prone to " + - "errors that have security implications. Use the WHATWG URL API " + - "instead. CVEs are not issued for `url.parse()` vulnerabilities.", - "DeprecationWarning", - "DEP0169", - ); - } - if ($isObject(url) && url instanceof Url) return url; var u = new Url(); diff --git a/src/js/node/vm.ts b/src/js/node/vm.ts index fd447006ef98a6..d02b67c8ac5d02 100644 --- a/src/js/node/vm.ts +++ b/src/js/node/vm.ts @@ -24,19 +24,19 @@ function measureMemory() { class Module { constructor() { - throwNotImplemented("node:vm Module"); + throwNotImplemented("node:vm.Module"); } } class SourceTextModule { constructor() { - throwNotImplemented("node:vm Module"); + throwNotImplemented("node:vm.SourceTextModule"); } } class SyntheticModule { constructor() { - throwNotImplemented("node:vm Module"); + throwNotImplemented("node:vm.SyntheticModule"); } } diff --git a/src/js/node/worker_threads.ts b/src/js/node/worker_threads.ts index 4cd282398f67b4..8d5eabb642e158 100644 --- a/src/js/node/worker_threads.ts +++ b/src/js/node/worker_threads.ts @@ -234,11 +234,11 @@ class Worker extends EventEmitter { } throw e; } - this.#worker.addEventListener("close", this.#onClose.bind(this)); + this.#worker.addEventListener("close", this.#onClose.bind(this), { once: true }); this.#worker.addEventListener("error", this.#onError.bind(this)); this.#worker.addEventListener("message", this.#onMessage.bind(this)); this.#worker.addEventListener("messageerror", this.#onMessageError.bind(this)); - this.#worker.addEventListener("open", this.#onOpen.bind(this)); + this.#worker.addEventListener("open", this.#onOpen.bind(this), { once: true }); if (this.#urlToRevoke) { const url = this.#urlToRevoke; diff --git a/src/js_ast.zig b/src/js_ast.zig index f7187cbfe953e6..530eb4ee54ebd2 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -21,7 +21,6 @@ const allocators = @import("allocators.zig"); const JSC = bun.JSC; const RefCtx = @import("./ast/base.zig").RefCtx; const JSONParser = bun.JSON; -const is_bindgen = false; const ComptimeStringMap = bun.ComptimeStringMap; const JSPrinter = @import("./js_printer.zig"); const js_lexer = @import("./js_lexer.zig"); @@ -3203,9 +3202,9 @@ pub const Stmt = struct { }; pub fn StoredData(tag: Tag) type { - const T = std.meta.FieldType(Data, tag); + const T = @FieldType(Data, tag); return switch (@typeInfo(T)) { - .Pointer => |ptr| ptr.child, + .pointer => |ptr| ptr.child, else => T, }; } @@ -5307,7 +5306,7 @@ pub const Expr = struct { bun.assert_eql(@sizeOf(Data), 24); // Do not increase the size of Expr } - pub fn as(data: Data, comptime tag: Tag) ?std.meta.FieldType(Data, tag) { + pub fn as(data: Data, comptime tag: Tag) ?@FieldType(Data, @tagName(tag)) { return if (data == tag) @field(data, @tagName(tag)) else null; } @@ -6044,7 +6043,7 @@ pub const Expr = struct { p: anytype, comptime kind: enum { loose, strict }, ) Equality { - comptime bun.assert(@typeInfo(@TypeOf(p)).Pointer.size == .One); // pass *Parser + comptime bun.assert(@typeInfo(@TypeOf(p)).pointer.size == .one); // pass *Parser // https://dorey.github.io/JavaScript-Equality-Table/ switch (left) { @@ -6330,9 +6329,9 @@ pub const Expr = struct { }; pub fn StoredData(tag: Tag) type { - const T = std.meta.FieldType(Data, tag); + const T = @FieldType(Data, tag); return switch (@typeInfo(T)) { - .Pointer => |ptr| ptr.child, + .pointer => |ptr| ptr.child, else => T, }; } @@ -8143,7 +8142,6 @@ pub const Macro = struct { source: *const logger.Source, id: i32, ) MacroError!Expr { - if (comptime is_bindgen) return undefined; const macro_callback = macro.vm.macros.get(id) orelse return caller; const result = js.JSObjectCallAsFunctionReturnValueHoldingAPILock( @@ -8177,7 +8175,7 @@ pub const Macro = struct { this: *Run, value: JSC.JSValue, ) MacroError!Expr { - return try switch (JSC.ConsoleObject.Formatter.Tag.get(value, this.global).tag) { + return switch (JSC.ConsoleObject.Formatter.Tag.get(value, this.global).tag) { .Error => this.coerce(value, .Error), .Undefined => this.coerce(value, .Undefined), .Null => this.coerce(value, .Null), @@ -8529,7 +8527,7 @@ pub const Macro = struct { }); } - extern "C" fn Bun__startMacro(function: *const anyopaque, *anyopaque) void; + extern "c" fn Bun__startMacro(function: *const anyopaque, *anyopaque) void; }; }; diff --git a/src/js_lexer.zig b/src/js_lexer.zig index 251cd7c08a5807..7c9dd41e91f5f7 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -187,7 +187,7 @@ fn NewLexer_( } pub fn syntaxError(self: *LexerType) !void { - @setCold(true); + @branchHint(.cold); // Only add this if there is not already an error. // It is possible that there is a more descriptive error already emitted. @@ -198,20 +198,20 @@ fn NewLexer_( } pub fn addDefaultError(self: *LexerType, msg: []const u8) !void { - @setCold(true); + @branchHint(.cold); self.addError(self.start, "{s}", .{msg}, true); return Error.SyntaxError; } pub fn addSyntaxError(self: *LexerType, _loc: usize, comptime fmt: []const u8, args: anytype) !void { - @setCold(true); + @branchHint(.cold); self.addError(_loc, fmt, args, false); return Error.SyntaxError; } pub fn addError(self: *LexerType, _loc: usize, comptime format: []const u8, args: anytype, _: bool) void { - @setCold(true); + @branchHint(.cold); if (self.is_log_disabled) return; var __loc = logger.usize2Loc(_loc); @@ -224,7 +224,7 @@ fn NewLexer_( } pub fn addRangeError(self: *LexerType, r: logger.Range, comptime format: []const u8, args: anytype, _: bool) !void { - @setCold(true); + @branchHint(.cold); if (self.is_log_disabled) return; if (self.prev_error_loc.eql(r.loc)) { @@ -241,7 +241,7 @@ fn NewLexer_( } pub fn addRangeErrorWithNotes(self: *LexerType, r: logger.Range, comptime format: []const u8, args: anytype, notes: []const logger.Data) !void { - @setCold(true); + @branchHint(.cold); if (self.is_log_disabled) return; if (self.prev_error_loc.eql(r.loc)) { diff --git a/src/js_parser.zig b/src/js_parser.zig index 69a7b91c021c9f..c99fd26db8bf12 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -2600,7 +2600,7 @@ const InvalidLoc = struct { }; pub fn addError(loc: InvalidLoc, log: *logger.Log, source: *const logger.Source) void { - @setCold(true); + @branchHint(.cold); const text = switch (loc.kind) { .spread => "Unexpected trailing comma after rest element", .parentheses => "Unexpected parentheses in binding pattern", @@ -5617,7 +5617,7 @@ fn NewParser_( } // Output.print("\nStmt: {s} - {d}\n", .{ @typeName(@TypeOf(t)), loc.start }); - if (@typeInfo(Type) == .Pointer) { + if (@typeInfo(Type) == .pointer) { // ExportFrom normally becomes import records during the visiting pass // However, we skip the visiting pass in this mode // So we must generate a minimum version of it here. @@ -5707,7 +5707,7 @@ fn NewParser_( } // Output.print("\nExpr: {s} - {d}\n", .{ @typeName(@TypeOf(t)), loc.start }); - if (@typeInfo(Type) == .Pointer) { + if (@typeInfo(Type) == .pointer) { if (comptime only_scan_imports_and_do_not_visit) { if (Type == *E.Call) { const call: *E.Call = t; @@ -5743,7 +5743,7 @@ fn NewParser_( } pub fn b(p: *P, t: anytype, loc: logger.Loc) Binding { - if (@typeInfo(@TypeOf(t)) == .Pointer) { + if (@typeInfo(@TypeOf(t)) == .pointer) { return Binding.init(t, loc); } else { return Binding.alloc(p.allocator, t, loc); @@ -6812,7 +6812,10 @@ fn NewParser_( if (p.lexer.jsx_pragma.jsxRuntime()) |runtime| { if (options.JSX.RuntimeMap.get(runtime.text)) |jsx_runtime| { - p.options.jsx.runtime = jsx_runtime; + p.options.jsx.runtime = jsx_runtime.runtime; + if (jsx_runtime.development) |dev| { + p.options.jsx.development = dev; + } } else { // make this a warning instead of an error because we don't support "preserve" right now try p.log.addRangeWarningFmt(p.source, runtime.range, p.allocator, "Unsupported JSX runtime: \"{s}\"", .{runtime.text}); @@ -9213,7 +9216,7 @@ fn NewParser_( } fn validateImportType(p: *P, import_tag: ImportRecord.Tag, stmt: *S.Import) !void { - @setCold(true); + @branchHint(.cold); if (import_tag.loader() != null) { p.import_records.items[stmt.import_record_index].tag = import_tag; @@ -14760,8 +14763,8 @@ fn NewParser_( } pub fn panic(p: *P, comptime fmt: string, args: anytype) noreturn { + @branchHint(.cold); p.panicLoc(fmt, args, null); - @setCold(true); } pub fn panicLoc(p: *P, comptime fmt: string, args: anytype, loc: ?logger.Loc) noreturn { diff --git a/src/js_printer.zig b/src/js_printer.zig index 6ab28eb324c5d3..42bfb573a6a9fd 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -346,7 +346,11 @@ pub fn writePreQuotedString(text_in: []const u8, comptime Writer: type, writer: }, '\t' => { - try writer.writeAll("\\t"); + if (quote_char == '`') { + try writer.writeAll("\t"); + } else { + try writer.writeAll("\\t"); + } i += 1; }, @@ -1905,7 +1909,7 @@ fn NewPrinter( return printClauseItemAs(p, item, .@"export"); } - fn printClauseItemAs(p: *Printer, item: js_ast.ClauseItem, comptime as: @Type(.EnumLiteral)) void { + fn printClauseItemAs(p: *Printer, item: js_ast.ClauseItem, comptime as: @Type(.enum_literal)) void { const name = p.renamer.nameForSymbol(item.name.ref.?); if (comptime as == .import) { @@ -5974,7 +5978,7 @@ pub fn printWithWriterAndPlatform( printer.printFunc(func); } else { // Special-case lazy-export AST - // @branchHint(.unlikely) + @branchHint(.unlikely); printer.printFnArgs(func.open_parens_loc, func.args, func.flags.contains(.has_rest_arg), false); printer.printSpace(); printer.print("{\n"); diff --git a/src/jsc.zig b/src/jsc.zig index ebb70db42f5bb3..970a289fd83928 100644 --- a/src/jsc.zig +++ b/src/jsc.zig @@ -5,7 +5,6 @@ pub usingnamespace @import("./bun.js/bindings/exports.zig"); pub usingnamespace @import("./bun.js/event_loop.zig"); pub usingnamespace @import("./bun.js/javascript.zig"); pub usingnamespace @import("./bun.js/module_loader.zig"); -pub const is_bindgen = false; pub const Debugger = @import("./bun.js/bindings/Debugger.zig").Debugger; pub const napi = @import("./napi/napi.zig"); pub const RareData = @import("./bun.js/rare_data.zig"); @@ -82,7 +81,6 @@ pub const jsNumber = @This().JSValue.jsNumber; const __jsc_log = Output.scoped(.JSC, true); pub inline fn markBinding(src: std.builtin.SourceLocation) void { - if (comptime is_bindgen) unreachable; __jsc_log("{s} ({s}:{d})", .{ src.fn_name, src.file, src.line }); } pub const Subprocess = API.Bun.Subprocess; diff --git a/src/json_parser.zig b/src/json_parser.zig index c7a95ead6e7a36..63cd0bfecd1b25 100644 --- a/src/json_parser.zig +++ b/src/json_parser.zig @@ -87,7 +87,7 @@ const HashMapPool = struct { fn newExpr(t: anytype, loc: logger.Loc) Expr { const Type = @TypeOf(t); - if (comptime @typeInfo(Type) == .Pointer) { + if (comptime @typeInfo(Type) == .pointer) { @compileError("Unexpected pointer"); } @@ -533,7 +533,7 @@ pub fn toAST( const type_info: std.builtin.Type = @typeInfo(Type); switch (type_info) { - .Bool => { + .bool => { return Expr{ .data = .{ .e_boolean = .{ .value = value, @@ -541,7 +541,7 @@ pub fn toAST( .loc = logger.Loc{}, }; }, - .Int => { + .int => { return Expr{ .data = .{ .e_number = .{ @@ -551,7 +551,7 @@ pub fn toAST( .loc = logger.Loc{}, }; }, - .Float => { + .float => { return Expr{ .data = .{ .e_number = .{ @@ -561,9 +561,9 @@ pub fn toAST( .loc = logger.Loc{}, }; }, - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => switch (@typeInfo(ptr_info.child)) { - .Array => { + .pointer => |ptr_info| switch (ptr_info.size) { + .one => switch (@typeInfo(ptr_info.child)) { + .array => { const Slice = []const std.meta.Elem(ptr_info.child); return try toAST(allocator, Slice, value.*); }, @@ -571,7 +571,7 @@ pub fn toAST( return try toAST(allocator, @TypeOf(value.*), value.*); }, }, - .Slice => { + .slice => { if (ptr_info.child == u8) { return Expr.init(js_ast.E.String, js_ast.E.String.init(value), logger.Loc.Empty); } @@ -583,7 +583,7 @@ pub fn toAST( }, else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"), }, - .Array => |Array| { + .array => |Array| { if (Array.child == u8) { return Expr.init(js_ast.E.String, js_ast.E.String.init(value), logger.Loc.Empty); } @@ -593,7 +593,7 @@ pub fn toAST( return Expr.init(js_ast.E.Array, js_ast.E.Array{ .items = exprs }, logger.Loc.Empty); }, - .Struct => |Struct| { + .@"struct" => |Struct| { const fields: []const std.builtin.Type.StructField = Struct.fields; var properties = try allocator.alloc(js_ast.G.Property, fields.len); var property_i: usize = 0; @@ -614,25 +614,25 @@ pub fn toAST( logger.Loc.Empty, ); }, - .Null => { + .null => { return Expr{ .data = .{ .e_null = .{} }, .loc = logger.Loc{} }; }, - .Optional => { + .optional => { if (value) |_value| { return try toAST(allocator, @TypeOf(_value), _value); } else { return Expr{ .data = .{ .e_null = .{} }, .loc = logger.Loc{} }; } }, - .Enum => { + .@"enum" => { _ = std.meta.intToEnum(Type, @intFromEnum(value)) catch { return Expr{ .data = .{ .e_null = .{} }, .loc = logger.Loc{} }; }; return toAST(allocator, string, @as(string, @tagName(value))); }, - .ErrorSet => return try toAST(allocator, []const u8, bun.asByteSlice(@errorName(value))), - .Union => |Union| { + .error_set => return try toAST(allocator, []const u8, bun.asByteSlice(@errorName(value))), + .@"union" => |Union| { const info = Union; if (info.tag_type) |UnionTagType| { inline for (info.fields) |u_field| { @@ -650,7 +650,7 @@ pub fn toAST( @field(value, u_field.name), ), .is_comptime = false, - .default_value = undefined, + .default_value_ptr = undefined, .alignment = @alignOf( @TypeOf( @field(value, u_field.name), diff --git a/src/libarchive/libarchive-bindings.zig b/src/libarchive/libarchive-bindings.zig index d9bd69630a80bf..f8ec3f8f797389 100644 --- a/src/libarchive/libarchive-bindings.zig +++ b/src/libarchive/libarchive-bindings.zig @@ -874,11 +874,11 @@ pub const Archive = opaque { }, result: T, - pub fn err(arch: *Archive, msg: []const u8) @This() { + pub fn initErr(arch: *Archive, msg: []const u8) @This() { return .{ .err = .{ .message = msg, .archive = arch } }; } - pub fn res(value: T) @This() { + pub fn initRes(value: T) @This() { return .{ .result = value }; } }; @@ -891,38 +891,38 @@ pub const Archive = opaque { switch (archive.readSupportFormatTar()) { .failed, .fatal, .warn => { - return Return.err(archive, "failed to enable tar format support"); + return Return.initErr(archive, "failed to enable tar format support"); }, else => {}, } switch (archive.readSupportFormatGnutar()) { .failed, .fatal, .warn => { - return Return.err(archive, "failed to enable gnutar format support"); + return Return.initErr(archive, "failed to enable gnutar format support"); }, else => {}, } switch (archive.readSupportFilterGzip()) { .failed, .fatal, .warn => { - return Return.err(archive, "failed to enable support for gzip compression"); + return Return.initErr(archive, "failed to enable support for gzip compression"); }, else => {}, } switch (archive.readSetOptions("read_concatenated_archives")) { .failed, .fatal, .warn => { - return Return.err(archive, "failed to set option `read_concatenated_archives`"); + return Return.initErr(archive, "failed to set option `read_concatenated_archives`"); }, else => {}, } switch (archive.readOpenMemory(tarball_bytes)) { .failed, .fatal, .warn => { - return Return.err(archive, "failed to read tarball"); + return Return.initErr(archive, "failed to read tarball"); }, else => {}, } - return Return.res(.{ + return Return.initRes(.{ .archive = archive, .filter = std.EnumSet(std.fs.File.Kind).initEmpty(), }); @@ -935,15 +935,15 @@ pub const Archive = opaque { pub fn readEntryData(this: *const @This(), allocator: std.mem.Allocator, archive: *Archive) OOM!Iterator.Result([]const u8) { const Return = Iterator.Result([]const u8); const size = this.entry.size(); - if (size < 0) return Return.err(archive, "invalid archive entry size"); + if (size < 0) return Return.initErr(archive, "invalid archive entry size"); const buf = try allocator.alloc(u8, @intCast(size)); const read = archive.readData(buf); if (read < 0) { - return Return.err(archive, "failed to read archive data"); + return Return.initErr(archive, "failed to read archive data"); } - return Return.res(buf[0..@intCast(read)]); + return Return.initRes(buf[0..@intCast(read)]); } }; @@ -954,18 +954,18 @@ pub const Archive = opaque { while (true) { return switch (this.archive.readNextHeader(&entry)) { .retry => continue, - .eof => Return.res(null), + .eof => Return.initRes(null), .ok => { const kind = bun.C.kindFromMode(entry.filetype()); if (this.filter.contains(kind)) continue; - return Return.res(.{ + return Return.initRes(.{ .entry = entry, .kind = kind, }); }, - else => Return.err(this.archive, "failed to read archive header"), + else => Return.initErr(this.archive, "failed to read archive header"), }; } } @@ -975,18 +975,18 @@ pub const Archive = opaque { switch (this.archive.readClose()) { .failed, .fatal, .warn => { - return Return.err(this.archive, "failed to close archive read"); + return Return.initErr(this.archive, "failed to close archive read"); }, else => {}, } switch (this.archive.readFree()) { .failed, .fatal, .warn => { - return Return.err(this.archive, "failed to free archive read"); + return Return.initErr(this.archive, "failed to free archive read"); }, else => {}, } - return Return.res({}); + return Return.initRes({}); } }; }; diff --git a/src/libarchive/libarchive.zig b/src/libarchive/libarchive.zig index 29c56875b515b0..f19bcd570598ee 100644 --- a/src/libarchive/libarchive.zig +++ b/src/libarchive/libarchive.zig @@ -262,7 +262,7 @@ pub const Archiver = struct { // it will require us to pull in libiconv // though we should probably validate the utf8 here nonetheless var pathname = entry.pathname(); - var tokenizer = std.mem.tokenize(u8, bun.asByteSlice(pathname), std.fs.path.sep_str); + var tokenizer = std.mem.tokenizeScalar(u8, bun.asByteSlice(pathname), std.fs.path.sep); comptime var depth_i: usize = 0; inline while (depth_i < depth_to_skip) : (depth_i += 1) { if (tokenizer.next() == null) continue :loop; diff --git a/src/linux_c.zig b/src/linux_c.zig index 7236b0bba61b71..d8cb012fdee596 100644 --- a/src/linux_c.zig +++ b/src/linux_c.zig @@ -1,6 +1,6 @@ const std = @import("std"); const bun = @import("root").bun; -pub extern "C" fn memmem(haystack: [*]const u8, haystacklen: usize, needle: [*]const u8, needlelen: usize) ?[*]const u8; +pub extern "c" fn memmem(haystack: [*]const u8, haystacklen: usize, needle: [*]const u8, needlelen: usize) ?[*]const u8; pub const SystemErrno = enum(u8) { SUCCESS = 0, EPERM = 1, @@ -586,7 +586,7 @@ pub const RWFFlagSupport = enum(u8) { if (comptime !bun.Environment.isLinux) return false; switch (rwf_bool.load(.monotonic)) { .unknown => { - if (isLinuxKernelVersionWithBuggyRWF_NONBLOCK()) { + if (isLinuxKernelVersionWithBuggyRWF_NONBLOCK() or bun.getRuntimeFeatureFlag("BUN_FEATURE_FLAG_DISABLE_RWF_NONBLOCK")) { rwf_bool.store(.unsupported, .monotonic); return false; } @@ -606,7 +606,7 @@ pub const RWFFlagSupport = enum(u8) { } }; -pub extern "C" fn sys_preadv2( +pub extern "c" fn sys_preadv2( fd: c_int, iov: [*]const std.posix.iovec, iovcnt: c_int, @@ -614,7 +614,7 @@ pub extern "C" fn sys_preadv2( flags: c_uint, ) isize; -pub extern "C" fn sys_pwritev2( +pub extern "c" fn sys_pwritev2( fd: c_int, iov: [*]const std.posix.iovec_const, iovcnt: c_int, @@ -630,8 +630,8 @@ pub const RENAME_NOREPLACE = 1 << 0; pub const RENAME_EXCHANGE = 1 << 1; pub const RENAME_WHITEOUT = 1 << 2; -pub extern "C" fn quick_exit(code: c_int) noreturn; -pub extern "C" fn memrchr(ptr: [*]const u8, val: c_int, len: usize) ?[*]const u8; +pub extern "c" fn quick_exit(code: c_int) noreturn; +pub extern "c" fn memrchr(ptr: [*]const u8, val: c_int, len: usize) ?[*]const u8; export fn sys_epoll_pwait2(epfd: i32, events: ?[*]std.os.linux.epoll_event, maxevents: i32, timeout: ?*const std.os.linux.timespec, sigmask: ?*const std.os.linux.sigset_t) isize { return @bitCast( @@ -642,6 +642,9 @@ export fn sys_epoll_pwait2(epfd: i32, events: ?[*]std.os.linux.epoll_event, maxe @bitCast(@as(isize, @intCast(maxevents))), @intFromPtr(timeout), @intFromPtr(sigmask), + // This is the correct value. glibc claims to pass `sizeof sigset_t` for this argument, + // which would be 128, but they actually pass 8 which is what the kernel expects. + // https://github.com/ziglang/zig/issues/12715 8, ), ); @@ -699,10 +702,10 @@ comptime { _ = fstat64; _ = fstatat; _ = statx; - @export(stat, .{ .name = "stat64" }); - @export(lstat, .{ .name = "lstat64" }); - @export(fstat, .{ .name = "fstat64" }); - @export(fstatat, .{ .name = "fstatat64" }); + @export(&stat, .{ .name = "stat64" }); + @export(&lstat, .{ .name = "lstat64" }); + @export(&fstat, .{ .name = "fstat64" }); + @export(&fstatat, .{ .name = "fstatat64" }); } // ********************************************************************************* diff --git a/src/logger.zig b/src/logger.zig index cddd6d75e9d43c..20457169915de6 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -729,23 +729,23 @@ pub const Log = struct { } pub fn addDebugFmt(log: *Log, source: ?*const Source, l: Loc, allocator: std.mem.Allocator, comptime text: string, args: anytype) OOM!void { - if (!Kind.shouldPrint(.debug, log.level)) return; - - @setCold(true); - try log.addMsg(.{ - .kind = .debug, - .data = try rangeData(source, Range{ .loc = l }, try allocPrint(allocator, text, args)).cloneLineText(log.clone_line_text, log.msgs.allocator), - }); + if (Kind.shouldPrint(.debug, log.level)) { + @branchHint(.cold); + try log.addMsg(.{ + .kind = .debug, + .data = try rangeData(source, Range{ .loc = l }, try allocPrint(allocator, text, args)).cloneLineText(log.clone_line_text, log.msgs.allocator), + }); + } } pub fn addVerbose(log: *Log, source: ?*const Source, loc: Loc, text: string) OOM!void { - if (!Kind.shouldPrint(.verbose, log.level)) return; - - @setCold(true); - try log.addMsg(.{ - .kind = .verbose, - .data = rangeData(source, Range{ .loc = loc }, text), - }); + if (Kind.shouldPrint(.verbose, log.level)) { + @branchHint(.cold); + try log.addMsg(.{ + .kind = .verbose, + .data = rangeData(source, Range{ .loc = loc }, text), + }); + } } pub fn toJS(this: Log, global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, message: string) JSC.JSValue { @@ -871,7 +871,7 @@ pub const Log = struct { pub const clearAndFree = deinit; pub fn addVerboseWithNotes(log: *Log, source: ?*const Source, loc: Loc, text: string, notes: []Data) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.verbose, log.level)) return; try log.addMsg(.{ @@ -882,7 +882,7 @@ pub const Log = struct { } inline fn allocPrint(allocator: std.mem.Allocator, comptime fmt: string, args: anytype) OOM!string { - return try switch (Output.enable_ansi_colors) { + return switch (Output.enable_ansi_colors) { inline else => |enable_ansi_colors| std.fmt.allocPrint(allocator, Output.prettyFmt(fmt, enable_ansi_colors), args), }; } @@ -950,7 +950,7 @@ pub const Log = struct { import_kind: ImportKind, err: anyerror, ) OOM!void { - @setCold(true); + @branchHint(.cold); return try addResolveErrorWithLevel(log, source, r, allocator, fmt, args, import_kind, false, .err, err); } @@ -963,12 +963,12 @@ pub const Log = struct { args: anytype, import_kind: ImportKind, ) OOM!void { - @setCold(true); + @branchHint(.cold); return try addResolveErrorWithLevel(log, source, r, allocator, fmt, args, import_kind, true, .err, error.ModuleNotFound); } pub fn addRangeError(log: *Log, source: ?*const Source, r: Range, text: string) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; try log.addMsg(.{ .kind = .err, @@ -977,7 +977,7 @@ pub const Log = struct { } pub fn addRangeErrorFmt(log: *Log, source: ?*const Source, r: Range, allocator: std.mem.Allocator, comptime text: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; try log.addMsg(.{ .kind = .err, @@ -986,7 +986,7 @@ pub const Log = struct { } pub fn addRangeErrorFmtWithNotes(log: *Log, source: ?*const Source, r: Range, allocator: std.mem.Allocator, notes: []Data, comptime fmt: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; try log.addMsg(.{ .kind = .err, @@ -996,7 +996,7 @@ pub const Log = struct { } pub fn addErrorFmt(log: *Log, source: ?*const Source, l: Loc, allocator: std.mem.Allocator, comptime text: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; try log.addMsg(.{ .kind = .err, @@ -1006,7 +1006,7 @@ pub const Log = struct { // TODO(dylan-conway): rename and replace `addErrorFmt` pub fn addErrorFmtOpts(log: *Log, allocator: std.mem.Allocator, comptime fmt: string, args: anytype, opts: AddErrorOptions) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; try log.addMsg(.{ .kind = .err, @@ -1035,7 +1035,7 @@ pub const Log = struct { } pub fn addZigErrorWithNote(log: *Log, allocator: std.mem.Allocator, err: anyerror, comptime noteFmt: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; var notes = try allocator.alloc(Data, 1); @@ -1049,7 +1049,7 @@ pub const Log = struct { } pub fn addRangeWarning(log: *Log, source: ?*const Source, r: Range, text: string) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; try log.addMsg(.{ @@ -1059,7 +1059,7 @@ pub const Log = struct { } pub fn addWarningFmt(log: *Log, source: ?*const Source, l: Loc, allocator: std.mem.Allocator, comptime text: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; try log.addMsg(.{ @@ -1069,7 +1069,7 @@ pub const Log = struct { } pub fn addWarningFmtLineCol(log: *Log, filepath: []const u8, line: u32, col: u32, allocator: std.mem.Allocator, comptime text: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; @@ -1089,7 +1089,7 @@ pub const Log = struct { } pub fn addRangeWarningFmt(log: *Log, source: ?*const Source, r: Range, allocator: std.mem.Allocator, comptime text: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; try log.addMsg(.{ @@ -1109,7 +1109,7 @@ pub const Log = struct { note_args: anytype, note_range: Range, ) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; @@ -1124,7 +1124,7 @@ pub const Log = struct { } pub fn addRangeWarningFmtWithNotes(log: *Log, source: ?*const Source, r: Range, allocator: std.mem.Allocator, notes: []Data, comptime fmt: string, args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); log.warnings += 1; try log.addMsg(.{ .kind = .warn, @@ -1144,7 +1144,7 @@ pub const Log = struct { note_args: anytype, note_range: Range, ) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.err, log.level)) return; log.errors += 1; @@ -1159,7 +1159,7 @@ pub const Log = struct { } pub fn addWarning(log: *Log, source: ?*const Source, l: Loc, text: string) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; try log.addMsg(.{ @@ -1169,7 +1169,7 @@ pub const Log = struct { } pub fn addWarningWithNote(log: *Log, source: ?*const Source, l: Loc, allocator: std.mem.Allocator, warn: string, comptime note_fmt: string, note_args: anytype) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; @@ -1184,7 +1184,7 @@ pub const Log = struct { } pub fn addRangeDebug(log: *Log, source: ?*const Source, r: Range, text: string) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.debug, log.level)) return; try log.addMsg(.{ .kind = .debug, @@ -1193,7 +1193,7 @@ pub const Log = struct { } pub fn addRangeDebugWithNotes(log: *Log, source: ?*const Source, r: Range, text: string, notes: []Data) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.debug, log.level)) return; // log.de += 1; try log.addMsg(.{ @@ -1204,7 +1204,7 @@ pub const Log = struct { } pub fn addRangeErrorWithNotes(log: *Log, source: ?*const Source, r: Range, text: string, notes: []Data) OOM!void { - @setCold(true); + @branchHint(.cold); log.errors += 1; try log.addMsg(.{ .kind = Kind.err, @@ -1214,7 +1214,7 @@ pub const Log = struct { } pub fn addRangeWarningWithNotes(log: *Log, source: ?*const Source, r: Range, text: string, notes: []Data) OOM!void { - @setCold(true); + @branchHint(.cold); if (!Kind.shouldPrint(.warn, log.level)) return; log.warnings += 1; try log.addMsg(.{ @@ -1229,7 +1229,7 @@ pub const Log = struct { } pub fn addError(self: *Log, _source: ?*const Source, loc: Loc, text: string) OOM!void { - @setCold(true); + @branchHint(.cold); self.errors += 1; try self.addMsg(.{ .kind = .err, .data = rangeData(_source, Range{ .loc = loc }, text) }); } @@ -1243,7 +1243,7 @@ pub const Log = struct { // TODO(dylan-conway): rename and replace `addError` pub fn addErrorOpts(self: *Log, text: string, opts: AddErrorOptions) OOM!void { - @setCold(true); + @branchHint(.cold); self.errors += 1; try self.addMsg(.{ .kind = .err, diff --git a/src/main.zig b/src/main.zig index 1df928f583cbe6..5dfc2f2bac11ef 100644 --- a/src/main.zig +++ b/src/main.zig @@ -16,8 +16,8 @@ comptime { } extern fn bun_warn_avx_missing(url: [*:0]const u8) void; -pub extern "C" var _environ: ?*anyopaque; -pub extern "C" var environ: ?*anyopaque; +pub extern "c" var _environ: ?*anyopaque; +pub extern "c" var environ: ?*anyopaque; pub fn main() void { bun.crash_handler.init(); @@ -27,8 +27,8 @@ pub fn main() void { .mask = std.posix.empty_sigset, .flags = 0, }; - std.posix.sigaction(std.posix.SIG.PIPE, &act, null) catch {}; - std.posix.sigaction(std.posix.SIG.XFSZ, &act, null) catch {}; + std.posix.sigaction(std.posix.SIG.PIPE, &act, null); + std.posix.sigaction(std.posix.SIG.XFSZ, &act, null); } // This should appear before we make any calls at all to libuv. @@ -59,28 +59,6 @@ pub fn main() void { bun.Global.exit(0); } -pub const overrides = struct { - pub const mem = struct { - extern "C" fn wcslen(s: [*:0]const u16) usize; - - pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const T) usize { - if (comptime T == u16 and sentinel == 0 and Environment.isWindows) { - return wcslen(p); - } - - if (comptime T == u8 and sentinel == 0) { - return bun.C.strlen(p); - } - - var i: usize = 0; - while (p[i] != sentinel) { - i += 1; - } - return i; - } - }; -}; - pub export fn Bun__panic(msg: [*]const u8, len: usize) noreturn { Output.panic("{s}", .{msg[0..len]}); } diff --git a/src/meta.zig b/src/meta.zig index d70ee0af271581..3b29f33bb080ec 100644 --- a/src/meta.zig +++ b/src/meta.zig @@ -5,8 +5,8 @@ pub usingnamespace std.meta; pub fn OptionalChild(comptime T: type) type { const tyinfo = @typeInfo(T); - if (tyinfo != .Pointer) @compileError("OptionalChild(T) requires that T be a pointer to an optional type."); - const child = @typeInfo(tyinfo.Pointer.child); + if (tyinfo != .pointer) @compileError("OptionalChild(T) requires that T be a pointer to an optional type."); + const child = @typeInfo(tyinfo.pointer.child); if (child != .Optional) @compileError("OptionalChild(T) requires that T be a pointer to an optional type."); return child.Optional.child; } @@ -14,8 +14,8 @@ pub fn OptionalChild(comptime T: type) type { pub fn EnumFields(comptime T: type) []const std.builtin.Type.EnumField { const tyinfo = @typeInfo(T); return switch (tyinfo) { - .Union => std.meta.fields(tyinfo.Union.tag_type.?), - .Enum => tyinfo.Enum.fields, + .@"union" => std.meta.fields(tyinfo.@"union".tag_type.?), + .@"enum" => tyinfo.@"enum".fields, else => { @compileError("Used `EnumFields(T)` on a type that is not an `enum` or a `union(enum)`"); }, @@ -24,7 +24,7 @@ pub fn EnumFields(comptime T: type) []const std.builtin.Type.EnumField { pub fn ReturnOfMaybe(comptime function: anytype) type { const Func = @TypeOf(function); - const typeinfo: std.builtin.Type.Fn = @typeInfo(Func).Fn; + const typeinfo: std.builtin.Type.Fn = @typeInfo(Func).@"fn"; const MaybeType = typeinfo.return_type orelse @compileError("Expected the function to have a return type"); return MaybeResult(MaybeType); } @@ -32,7 +32,7 @@ pub fn ReturnOfMaybe(comptime function: anytype) type { pub fn MaybeResult(comptime MaybeType: type) type { const maybe_ty_info = @typeInfo(MaybeType); - const maybe = maybe_ty_info.Union; + const maybe = maybe_ty_info.@"union"; if (maybe.fields.len != 2) @compileError("Expected the Maybe type to be a union(enum) with two variants"); if (!std.mem.eql(u8, maybe.fields[0].name, "err")) { @@ -51,7 +51,7 @@ pub fn ReturnOf(comptime function: anytype) type { } pub fn ReturnOfType(comptime Type: type) type { - const typeinfo: std.builtin.Type.Fn = @typeInfo(Type).Fn; + const typeinfo: std.builtin.Type.Fn = @typeInfo(Type).@"fn"; return typeinfo.return_type orelse void; } @@ -62,15 +62,16 @@ pub fn typeName(comptime Type: type) []const u8 { /// partially emulates behaviour of @typeName in previous Zig versions, /// converting "some.namespace.MyType" to "MyType" -pub fn typeBaseName(comptime fullname: [:0]const u8) [:0]const u8 { +pub inline fn typeBaseName(comptime fullname: [:0]const u8) [:0]const u8 { + @setEvalBranchQuota(1_000_000); // leave type name like "namespace.WrapperType(namespace.MyType)" as it is const baseidx = comptime std.mem.indexOf(u8, fullname, "("); - if (baseidx != null) return fullname; + if (baseidx != null) return comptime fullname; const idx = comptime std.mem.lastIndexOf(u8, fullname, "."); const name = if (idx == null) fullname else fullname[(idx.? + 1)..]; - return comptime std.fmt.comptimePrint("{s}", .{name}); + return comptime name; } pub fn enumFieldNames(comptime Type: type) []const []const u8 { @@ -103,10 +104,10 @@ pub fn banFieldType(comptime Container: type, comptime T: type) void { // *[n]T -> T pub fn Item(comptime T: type) type { switch (@typeInfo(T)) { - .Pointer => |ptr| { - if (ptr.size == .One) { + .pointer => |ptr| { + if (ptr.size == .one) { switch (@typeInfo(ptr.child)) { - .Array => |array| { + .array => |array| { return array.child; }, else => {}, @@ -183,14 +184,14 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type { tuple_fields[i] = .{ .name = std.fmt.bufPrintZ(&num_buf, "{d}", .{i}) catch unreachable, .type = T, - .default_value = null, + .default_value_ptr = null, .is_comptime = false, .alignment = if (@sizeOf(T) > 0) @alignOf(T) else 0, }; } return @Type(.{ - .Struct = .{ + .@"struct" = .{ .is_tuple = true, .layout = .auto, .decls = &.{}, @@ -207,14 +208,14 @@ pub fn hasStableMemoryLayout(comptime T: type) bool { .Bool => true, .Int => true, .Float => true, - .Enum => { + .@"enum" => { // not supporting this rn - if (tyinfo.Enum.is_exhaustive) return false; - return hasStableMemoryLayout(tyinfo.Enum.tag_type); + if (tyinfo.@"enum".is_exhaustive) return false; + return hasStableMemoryLayout(tyinfo.@"enum".tag_type); }, - .Struct => switch (tyinfo.Struct.layout) { + .@"struct" => switch (tyinfo.@"struct".layout) { .auto => { - inline for (tyinfo.Struct.fields) |field| { + inline for (tyinfo.@"struct".fields) |field| { if (!hasStableMemoryLayout(field.field_type)) return false; } return true; @@ -222,11 +223,11 @@ pub fn hasStableMemoryLayout(comptime T: type) bool { .@"extern" => true, .@"packed" => false, }, - .Union => switch (tyinfo.Union.layout) { + .@"union" => switch (tyinfo.@"union".layout) { .auto => { - if (tyinfo.Union.tag_type == null or !hasStableMemoryLayout(tyinfo.Union.tag_type.?)) return false; + if (tyinfo.@"union".tag_type == null or !hasStableMemoryLayout(tyinfo.@"union".tag_type.?)) return false; - inline for (tyinfo.Union.fields) |field| { + inline for (tyinfo.@"union".fields) |field| { if (!hasStableMemoryLayout(field.type)) return false; } @@ -240,26 +241,27 @@ pub fn hasStableMemoryLayout(comptime T: type) bool { } pub fn isSimpleCopyType(comptime T: type) bool { + @setEvalBranchQuota(1_000_000); const tyinfo = @typeInfo(T); return switch (tyinfo) { - .Void => true, - .Bool => true, - .Int => true, - .Float => true, - .Enum => true, - .Struct => { - inline for (tyinfo.Struct.fields) |field| { + .void => true, + .bool => true, + .int => true, + .float => true, + .@"enum" => true, + .@"struct" => { + inline for (tyinfo.@"struct".fields) |field| { if (!isSimpleCopyType(field.type)) return false; } return true; }, - .Union => { - inline for (tyinfo.Union.fields) |field| { + .@"union" => { + inline for (tyinfo.@"union".fields) |field| { if (!isSimpleCopyType(field.type)) return false; } return true; }, - .Optional => return isSimpleCopyType(tyinfo.Optional.child), + .optional => return isSimpleCopyType(tyinfo.optional.child), else => false, }; } @@ -269,7 +271,7 @@ pub fn isScalar(comptime T: type) bool { i32, u32, i64, u64, f32, f64, bool => true, else => { const tyinfo = @typeInfo(T); - if (tyinfo == .Enum) return true; + if (tyinfo == .@"enum") return true; return false; }, }; @@ -278,12 +280,12 @@ pub fn isScalar(comptime T: type) bool { pub fn isSimpleEqlType(comptime T: type) bool { const tyinfo = @typeInfo(T); return switch (tyinfo) { - .Type => true, - .Void => true, - .Bool => true, - .Int => true, - .Float => true, - .Enum => true, + .type => true, + .void => true, + .bool => true, + .int => true, + .float => true, + .@"enum" => true, else => false, }; } @@ -295,30 +297,37 @@ pub const ListContainerType = enum { }; pub fn looksLikeListContainerType(comptime T: type) ?struct { list: ListContainerType, child: type } { const tyinfo = @typeInfo(T); - if (tyinfo == .Struct) { + if (tyinfo == .@"struct") { // Looks like array list - if (tyinfo.Struct.fields.len == 2 and - std.mem.eql(u8, tyinfo.Struct.fields[0].name, "items") and - std.mem.eql(u8, tyinfo.Struct.fields[1].name, "capacity")) - return .{ .list = .array_list, .child = std.meta.Child(tyinfo.Struct.fields[0].type) }; + if (tyinfo.@"struct".fields.len == 2 and + std.mem.eql(u8, tyinfo.@"struct".fields[0].name, "items") and + std.mem.eql(u8, tyinfo.@"struct".fields[1].name, "capacity")) + return .{ .list = .array_list, .child = std.meta.Child(tyinfo.@"struct".fields[0].type) }; // Looks like babylist - if (tyinfo.Struct.fields.len == 3 and - std.mem.eql(u8, tyinfo.Struct.fields[0].name, "ptr") and - std.mem.eql(u8, tyinfo.Struct.fields[1].name, "len") and - std.mem.eql(u8, tyinfo.Struct.fields[2].name, "cap")) - return .{ .list = .baby_list, .child = std.meta.Child(tyinfo.Struct.fields[0].type) }; + if (tyinfo.@"struct".fields.len == 3 and + std.mem.eql(u8, tyinfo.@"struct".fields[0].name, "ptr") and + std.mem.eql(u8, tyinfo.@"struct".fields[1].name, "len") and + std.mem.eql(u8, tyinfo.@"struct".fields[2].name, "cap")) + return .{ .list = .baby_list, .child = std.meta.Child(tyinfo.@"struct".fields[0].type) }; // Looks like SmallList - if (tyinfo.Struct.fields.len == 2 and - std.mem.eql(u8, tyinfo.Struct.fields[0].name, "capacity") and - std.mem.eql(u8, tyinfo.Struct.fields[1].name, "data")) return .{ + if (tyinfo.@"struct".fields.len == 2 and + std.mem.eql(u8, tyinfo.@"struct".fields[0].name, "capacity") and + std.mem.eql(u8, tyinfo.@"struct".fields[1].name, "data")) return .{ .list = .small_list, .child = std.meta.Child( - @typeInfo(tyinfo.Struct.fields[1].type).Union.fields[0].type, + @typeInfo(tyinfo.@"struct".fields[1].type).@"union".fields[0].type, ), }; } return null; } + +pub fn Tagged(comptime U: type, comptime T: type) type { + var info: std.builtin.Type.Union = @typeInfo(U).@"union"; + info.tag_type = T; + info.decls = &.{}; + return @Type(.{ .@"union" = info }); +} diff --git a/src/multi_array_list.zig b/src/multi_array_list.zig index 46fbe6a936b0b0..087b8a42741a15 100644 --- a/src/multi_array_list.zig +++ b/src/multi_array_list.zig @@ -24,11 +24,16 @@ pub fn MultiArrayList(comptime T: type) type { len: usize = 0, capacity: usize = 0, - pub const Elem = switch (@typeInfo(T)) { - .Struct => T, - .Union => |u| struct { - pub const Bare = - @Type(.{ .Union = .{ + pub const empty: Self = .{ + .bytes = undefined, + .len = 0, + .capacity = 0, + }; + + const Elem = switch (@typeInfo(T)) { + .@"struct" => T, + .@"union" => |u| struct { + pub const Bare = @Type(.{ .@"union" = .{ .layout = u.layout, .tag_type = null, .fields = u.fields, @@ -70,6 +75,12 @@ pub fn MultiArrayList(comptime T: type) type { len: usize, capacity: usize, + pub const empty: Slice = .{ + .ptrs = undefined, + .len = 0, + .capacity = 0, + }; + pub fn items(self: Slice, comptime field: Field) []FieldType(field) { const F = FieldType(field); if (self.capacity == 0) { @@ -85,9 +96,9 @@ pub fn MultiArrayList(comptime T: type) type { pub fn set(self: *Slice, index: usize, elem: T) void { const e = switch (@typeInfo(T)) { - .Struct => elem, - .Union => Elem.fromT(elem), - else => @compileError("unreachable"), + .@"struct" => elem, + .@"union" => Elem.fromT(elem), + else => unreachable, }; inline for (fields, 0..) |field_info, i| { self.items(@as(Field, @enumFromInt(i)))[index] = @field(e, field_info.name); @@ -100,14 +111,14 @@ pub fn MultiArrayList(comptime T: type) type { @field(result, field_info.name) = self.items(@as(Field, @enumFromInt(i)))[index]; } return switch (@typeInfo(T)) { - .Struct => result, - .Union => Elem.toT(result.tags, result.data), - else => @compileError("unreachable"), + .@"struct" => result, + .@"union" => Elem.toT(result.tags, result.data), + else => unreachable, }; } pub fn toMultiArrayList(self: Slice) Self { - if (self.ptrs.len == 0) { + if (self.ptrs.len == 0 or self.capacity == 0) { return .{}; } const unaligned_ptr = self.ptrs[sizes.fields[0]]; @@ -279,6 +290,7 @@ pub fn MultiArrayList(comptime T: type) type { self.insertAssumeCapacity(index, elem); } + /// Invalidates all element pointers. pub fn clearRetainingCapacity(this: *Self) void { this.len = 0; } @@ -292,9 +304,9 @@ pub fn MultiArrayList(comptime T: type) type { assert(index <= self.len); self.len += 1; const entry = switch (@typeInfo(T)) { - .Struct => elem, - .Union => Elem.fromT(elem), - else => @compileError("unreachable"), + .@"struct" => elem, + .@"union" => Elem.fromT(elem), + else => unreachable, }; const slices = self.slice(); inline for (fields, 0..) |field_info, field_index| { @@ -359,11 +371,8 @@ pub fn MultiArrayList(comptime T: type) type { /// If `new_len` is greater than zero, this may fail to reduce the capacity, /// but the data remains intact and the length is updated to new_len. pub fn shrinkAndFree(self: *Self, gpa: Allocator, new_len: usize) void { - if (new_len == 0) { - gpa.free(self.allocatedBytes()); - self.* = .{}; - return; - } + if (new_len == 0) return clearAndFree(self, gpa); + assert(new_len <= self.capacity); assert(new_len <= self.len); @@ -404,6 +413,11 @@ pub fn MultiArrayList(comptime T: type) type { self.* = other; } + pub fn clearAndFree(self: *Self, gpa: Allocator) void { + gpa.free(self.allocatedBytes()); + self.* = .{}; + } + /// Reduce length to `new_len`. /// Invalidates pointers to elements `items[new_len..]`. /// Keeps capacity the same. @@ -485,7 +499,7 @@ pub fn MultiArrayList(comptime T: type) type { /// `ctx` has the following method: /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool` - fn sortInternal(self: Self, a: usize, b: usize, ctx: anytype, comptime mode: enum { stable, unstable }) void { + fn sortInternal(self: Self, a: usize, b: usize, ctx: anytype, comptime mode: std.sort.Mode) void { const sort_context: struct { sub_ctx: @TypeOf(ctx), slice: Slice, @@ -493,7 +507,7 @@ pub fn MultiArrayList(comptime T: type) type { pub fn swap(sc: @This(), a_index: usize, b_index: usize) void { inline for (fields, 0..) |field_info, i| { if (@sizeOf(field_info.type) != 0) { - const field = @as(Field, @enumFromInt(i)); + const field: Field = @enumFromInt(i); const ptr = sc.slice.items(field); mem.swap(field_info.type, &ptr[a_index], &ptr[b_index]); } @@ -571,7 +585,7 @@ pub fn MultiArrayList(comptime T: type) type { } fn FieldType(comptime field: Field) type { - return meta.fieldInfo(Elem, field).type; + return @FieldType(Elem, @tagName(field)); } const Entry = entry: { @@ -579,11 +593,11 @@ pub fn MultiArrayList(comptime T: type) type { for (&entry_fields, sizes.fields) |*entry_field, i| entry_field.* = .{ .name = fields[i].name ++ "_ptr", .type = *fields[i].type, - .default_value = null, + .default_value_ptr = null, .is_comptime = fields[i].is_comptime, .alignment = fields[i].alignment, }; - break :entry @Type(.{ .Struct = .{ + break :entry @Type(.{ .@"struct" = .{ .layout = .@"extern", .fields = &entry_fields, .decls = &.{}, @@ -600,329 +614,10 @@ pub fn MultiArrayList(comptime T: type) type { } comptime { - if (builtin.mode == .Debug) { + if (builtin.zig_backend == .stage2_llvm and !builtin.strip_debug_info) { _ = &dbHelper; _ = &Slice.dbHelper; } } }; } - -test "basic usage" { - const ally = testing.allocator; - - const Foo = struct { - a: u32, - b: []const u8, - c: u8, - }; - - var list = MultiArrayList(Foo){}; - defer list.deinit(ally); - - try testing.expectEqual(@as(usize, 0), list.items(.a).len); - - try list.ensureTotalCapacity(ally, 2); - - list.appendAssumeCapacity(.{ - .a = 1, - .b = "foobar", - .c = 'a', - }); - - list.appendAssumeCapacity(.{ - .a = 2, - .b = "zigzag", - .c = 'b', - }); - - try testing.expectEqualSlices(u32, list.items(.a), &[_]u32{ 1, 2 }); - try testing.expectEqualSlices(u8, list.items(.c), &[_]u8{ 'a', 'b' }); - - try testing.expectEqual(@as(usize, 2), list.items(.b).len); - try testing.expectEqualStrings("foobar", list.items(.b)[0]); - try testing.expectEqualStrings("zigzag", list.items(.b)[1]); - - try list.append(ally, .{ - .a = 3, - .b = "fizzbuzz", - .c = 'c', - }); - - try testing.expectEqualSlices(u32, list.items(.a), &[_]u32{ 1, 2, 3 }); - try testing.expectEqualSlices(u8, list.items(.c), &[_]u8{ 'a', 'b', 'c' }); - - try testing.expectEqual(@as(usize, 3), list.items(.b).len); - try testing.expectEqualStrings("foobar", list.items(.b)[0]); - try testing.expectEqualStrings("zigzag", list.items(.b)[1]); - try testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]); - - // Add 6 more things to force a capacity increase. - for (0..6) |i| { - try list.append(ally, .{ - .a = @as(u32, @intCast(4 + i)), - .b = "whatever", - .c = @as(u8, @intCast('d' + i)), - }); - } - - try testing.expectEqualSlices( - u32, - &[_]u32{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }, - list.items(.a), - ); - try testing.expectEqualSlices( - u8, - &[_]u8{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' }, - list.items(.c), - ); - - list.shrinkAndFree(ally, 3); - - try testing.expectEqualSlices(u32, list.items(.a), &[_]u32{ 1, 2, 3 }); - try testing.expectEqualSlices(u8, list.items(.c), &[_]u8{ 'a', 'b', 'c' }); - - try testing.expectEqual(@as(usize, 3), list.items(.b).len); - try testing.expectEqualStrings("foobar", list.items(.b)[0]); - try testing.expectEqualStrings("zigzag", list.items(.b)[1]); - try testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]); - - list.set(try list.addOne(ally), .{ - .a = 4, - .b = "xnopyt", - .c = 'd', - }); - try testing.expectEqualStrings("xnopyt", list.pop().b); - try testing.expectEqual(@as(?u8, 'c'), if (list.popOrNull()) |elem| elem.c else null); - try testing.expectEqual(@as(u32, 2), list.pop().a); - try testing.expectEqual(@as(u8, 'a'), list.pop().c); - try testing.expectEqual(@as(?Foo, null), list.popOrNull()); -} - -// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes -// function used the @reduce code path. -test "regression test for @reduce bug" { - const ally = testing.allocator; - var list = MultiArrayList(struct { - tag: std.zig.Token.Tag, - start: u32, - }){}; - defer list.deinit(ally); - - try list.ensureTotalCapacity(ally, 20); - - try list.append(ally, .{ .tag = .keyword_const, .start = 0 }); - try list.append(ally, .{ .tag = .identifier, .start = 6 }); - try list.append(ally, .{ .tag = .equal, .start = 10 }); - try list.append(ally, .{ .tag = .builtin, .start = 12 }); - try list.append(ally, .{ .tag = .l_paren, .start = 19 }); - try list.append(ally, .{ .tag = .string_literal, .start = 20 }); - try list.append(ally, .{ .tag = .r_paren, .start = 25 }); - try list.append(ally, .{ .tag = .semicolon, .start = 26 }); - try list.append(ally, .{ .tag = .keyword_pub, .start = 29 }); - try list.append(ally, .{ .tag = .keyword_fn, .start = 33 }); - try list.append(ally, .{ .tag = .identifier, .start = 36 }); - try list.append(ally, .{ .tag = .l_paren, .start = 40 }); - try list.append(ally, .{ .tag = .r_paren, .start = 41 }); - try list.append(ally, .{ .tag = .identifier, .start = 43 }); - try list.append(ally, .{ .tag = .bang, .start = 51 }); - try list.append(ally, .{ .tag = .identifier, .start = 52 }); - try list.append(ally, .{ .tag = .l_brace, .start = 57 }); - try list.append(ally, .{ .tag = .identifier, .start = 63 }); - try list.append(ally, .{ .tag = .period, .start = 66 }); - try list.append(ally, .{ .tag = .identifier, .start = 67 }); - try list.append(ally, .{ .tag = .period, .start = 70 }); - try list.append(ally, .{ .tag = .identifier, .start = 71 }); - try list.append(ally, .{ .tag = .l_paren, .start = 75 }); - try list.append(ally, .{ .tag = .string_literal, .start = 76 }); - try list.append(ally, .{ .tag = .comma, .start = 113 }); - try list.append(ally, .{ .tag = .period, .start = 115 }); - try list.append(ally, .{ .tag = .l_brace, .start = 116 }); - try list.append(ally, .{ .tag = .r_brace, .start = 117 }); - try list.append(ally, .{ .tag = .r_paren, .start = 118 }); - try list.append(ally, .{ .tag = .semicolon, .start = 119 }); - try list.append(ally, .{ .tag = .r_brace, .start = 121 }); - try list.append(ally, .{ .tag = .eof, .start = 123 }); - - const tags = list.items(.tag); - try testing.expectEqual(tags[1], .identifier); - try testing.expectEqual(tags[2], .equal); - try testing.expectEqual(tags[3], .builtin); - try testing.expectEqual(tags[4], .l_paren); - try testing.expectEqual(tags[5], .string_literal); - try testing.expectEqual(tags[6], .r_paren); - try testing.expectEqual(tags[7], .semicolon); - try testing.expectEqual(tags[8], .keyword_pub); - try testing.expectEqual(tags[9], .keyword_fn); - try testing.expectEqual(tags[10], .identifier); - try testing.expectEqual(tags[11], .l_paren); - try testing.expectEqual(tags[12], .r_paren); - try testing.expectEqual(tags[13], .identifier); - try testing.expectEqual(tags[14], .bang); - try testing.expectEqual(tags[15], .identifier); - try testing.expectEqual(tags[16], .l_brace); - try testing.expectEqual(tags[17], .identifier); - try testing.expectEqual(tags[18], .period); - try testing.expectEqual(tags[19], .identifier); - try testing.expectEqual(tags[20], .period); - try testing.expectEqual(tags[21], .identifier); - try testing.expectEqual(tags[22], .l_paren); - try testing.expectEqual(tags[23], .string_literal); - try testing.expectEqual(tags[24], .comma); - try testing.expectEqual(tags[25], .period); - try testing.expectEqual(tags[26], .l_brace); - try testing.expectEqual(tags[27], .r_brace); - try testing.expectEqual(tags[28], .r_paren); - try testing.expectEqual(tags[29], .semicolon); - try testing.expectEqual(tags[30], .r_brace); - try testing.expectEqual(tags[31], .eof); -} - -test "ensure capacity on empty list" { - const ally = testing.allocator; - - const Foo = struct { - a: u32, - b: u8, - }; - - var list = MultiArrayList(Foo){}; - defer list.deinit(ally); - - try list.ensureTotalCapacity(ally, 2); - list.appendAssumeCapacity(.{ .a = 1, .b = 2 }); - list.appendAssumeCapacity(.{ .a = 3, .b = 4 }); - - try testing.expectEqualSlices(u32, &[_]u32{ 1, 3 }, list.items(.a)); - try testing.expectEqualSlices(u8, &[_]u8{ 2, 4 }, list.items(.b)); - - list.len = 0; - list.appendAssumeCapacity(.{ .a = 5, .b = 6 }); - list.appendAssumeCapacity(.{ .a = 7, .b = 8 }); - - try testing.expectEqualSlices(u32, &[_]u32{ 5, 7 }, list.items(.a)); - try testing.expectEqualSlices(u8, &[_]u8{ 6, 8 }, list.items(.b)); - - list.len = 0; - try list.ensureTotalCapacity(ally, 16); - - list.appendAssumeCapacity(.{ .a = 9, .b = 10 }); - list.appendAssumeCapacity(.{ .a = 11, .b = 12 }); - - try testing.expectEqualSlices(u32, &[_]u32{ 9, 11 }, list.items(.a)); - try testing.expectEqualSlices(u8, &[_]u8{ 10, 12 }, list.items(.b)); -} - -test "insert elements" { - const ally = testing.allocator; - - const Foo = struct { - a: u8, - b: u32, - }; - - var list = MultiArrayList(Foo){}; - defer list.deinit(ally); - - try list.insert(ally, 0, .{ .a = 1, .b = 2 }); - try list.ensureUnusedCapacity(ally, 1); - list.insertAssumeCapacity(1, .{ .a = 2, .b = 3 }); - - try testing.expectEqualSlices(u8, &[_]u8{ 1, 2 }, list.items(.a)); - try testing.expectEqualSlices(u32, &[_]u32{ 2, 3 }, list.items(.b)); -} - -test "union" { - const ally = testing.allocator; - - const Foo = union(enum) { - a: u32, - b: []const u8, - }; - - var list = MultiArrayList(Foo){}; - defer list.deinit(ally); - - try testing.expectEqual(@as(usize, 0), list.items(.tags).len); - - try list.ensureTotalCapacity(ally, 2); - - list.appendAssumeCapacity(.{ .a = 1 }); - list.appendAssumeCapacity(.{ .b = "zigzag" }); - - try testing.expectEqualSlices(meta.Tag(Foo), list.items(.tags), &.{ .a, .b }); - try testing.expectEqual(@as(usize, 2), list.items(.tags).len); - - list.appendAssumeCapacity(.{ .b = "foobar" }); - try testing.expectEqualStrings("zigzag", list.items(.data)[1].b); - try testing.expectEqualStrings("foobar", list.items(.data)[2].b); - - // Add 6 more things to force a capacity increase. - for (0..6) |i| { - try list.append(ally, .{ .a = @as(u32, @intCast(4 + i)) }); - } - - try testing.expectEqualSlices( - meta.Tag(Foo), - &.{ .a, .b, .b, .a, .a, .a, .a, .a, .a }, - list.items(.tags), - ); - try testing.expectEqual(list.get(0), .{ .a = 1 }); - try testing.expectEqual(list.get(1), .{ .b = "zigzag" }); - try testing.expectEqual(list.get(2), .{ .b = "foobar" }); - try testing.expectEqual(list.get(3), .{ .a = 4 }); - try testing.expectEqual(list.get(4), .{ .a = 5 }); - try testing.expectEqual(list.get(5), .{ .a = 6 }); - try testing.expectEqual(list.get(6), .{ .a = 7 }); - try testing.expectEqual(list.get(7), .{ .a = 8 }); - try testing.expectEqual(list.get(8), .{ .a = 9 }); - - list.shrinkAndFree(ally, 3); - - try testing.expectEqual(@as(usize, 3), list.items(.tags).len); - try testing.expectEqualSlices(meta.Tag(Foo), list.items(.tags), &.{ .a, .b, .b }); - - try testing.expectEqual(list.get(0), .{ .a = 1 }); - try testing.expectEqual(list.get(1), .{ .b = "zigzag" }); - try testing.expectEqual(list.get(2), .{ .b = "foobar" }); -} - -test "sorting a span" { - var list: MultiArrayList(struct { score: u32, chr: u8 }) = .{}; - defer list.deinit(testing.allocator); - - try list.ensureTotalCapacity(testing.allocator, 42); - for ( - // zig fmt: off - [42]u8{ 'b', 'a', 'c', 'a', 'b', 'c', 'b', 'c', 'b', 'a', 'b', 'a', 'b', 'c', 'b', 'a', 'a', 'c', 'c', 'a', 'c', 'b', 'a', 'c', 'a', 'b', 'b', 'c', 'c', 'b', 'a', 'b', 'a', 'b', 'c', 'b', 'a', 'a', 'c', 'c', 'a', 'c' }, - [42]u32{ 1, 1, 1, 2, 2, 2, 3, 3, 4, 3, 5, 4, 6, 4, 7, 5, 6, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 9, 10, 11, 10, 12, 11, 13, 11, 14, 12, 13, 12, 13, 14, 14 }, - // zig fmt: on - ) |chr, score| { - list.appendAssumeCapacity(.{ .chr = chr, .score = score }); - } - - const sliced = list.slice(); - list.sortSpan(6, 21, struct { - chars: []const u8, - - fn lessThan(ctx: @This(), a: usize, b: usize) bool { - return ctx.chars[a] < ctx.chars[b]; - } - }{ .chars = sliced.items(.chr) }); - - var i: u32 = 0; - var j: u32 = 6; - var c: u8 = 'a'; - - while (j < 21) { - i = j; - j += 5; - var n: u32 = 3; - for (sliced.items(.chr)[i..j], sliced.items(.score)[i..j]) |chr, score| { - try testing.expectEqual(score, n); - try testing.expectEqual(chr, c); - n += 1; - } - c += 1; - } -} diff --git a/src/napi/napi.zig b/src/napi/napi.zig index ff738aa8a0f687..0dce7c9bda5aa9 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -846,13 +846,9 @@ pub export fn napi_get_arraybuffer_info(env: napi_env, arraybuffer_: napi_value, len.* = slice.len; return env.ok(); } -pub export fn napi_is_typedarray(env: napi_env, value_: napi_value, result_: ?*bool) napi_status { - log("napi_is_typedarray", .{}); - const value = value_.get(); - const result = result_ orelse return env.invalidArg(); - result.* = value.jsTypeLoose().isTypedArray(); - return env.ok(); -} + +pub extern fn napi_is_typedarray(napi_env, napi_value, *bool) napi_status; + pub export fn napi_create_typedarray(env: napi_env, @"type": napi_typedarray_type, length: usize, arraybuffer_: napi_value, byte_offset: usize, result_: ?*napi_value) napi_status { log("napi_create_typedarray", .{}); const arraybuffer = arraybuffer_.get(); @@ -1240,15 +1236,7 @@ pub export fn napi_create_buffer_copy(env: napi_env, length: usize, data: [*]u8, return env.ok(); } -pub export fn napi_is_buffer(env: napi_env, value_: napi_value, result_: ?*bool) napi_status { - log("napi_is_buffer", .{}); - const result = result_ orelse { - return env.invalidArg(); - }; - const value = value_.get(); - result.* = value.isBuffer(env.toJS()); - return env.ok(); -} +extern fn napi_is_buffer(napi_env, napi_value, *bool) napi_status; pub export fn napi_get_buffer_info(env: napi_env, value_: napi_value, data: ?*[*]u8, length: ?*usize) napi_status { log("napi_get_buffer_info", .{}); const value = value_.get(); diff --git a/src/node-fallbacks/bun.lock b/src/node-fallbacks/bun.lock index 9d89c803db3b1c..26187aaf6f5de7 100644 --- a/src/node-fallbacks/bun.lock +++ b/src/node-fallbacks/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "fallbacks", diff --git a/src/options.zig b/src/options.zig index 2e097d1c516c09..5388884980653d 100644 --- a/src/options.zig +++ b/src/options.zig @@ -697,7 +697,7 @@ pub const Loader = enum(u8) { pub fn canBeRunByBun(this: Loader) bool { return switch (this) { - .jsx, .js, .ts, .tsx, .json, .wasm, .bunsh => true, + .jsx, .js, .ts, .tsx, .wasm, .bunsh => true, else => false, }; } @@ -991,13 +991,18 @@ pub const ESMConditions = struct { }; pub const JSX = struct { - pub const RuntimeMap = bun.ComptimeStringMap(JSX.Runtime, .{ - .{ "classic", .classic }, - .{ "automatic", .automatic }, - .{ "react", .classic }, - .{ "react-jsx", .automatic }, - .{ "react-jsxdev", .automatic }, - .{ "solid", .solid }, + const RuntimeDevelopmentPair = struct { + runtime: JSX.Runtime, + development: ?bool, + }; + + pub const RuntimeMap = bun.ComptimeStringMap(RuntimeDevelopmentPair, .{ + .{ "classic", RuntimeDevelopmentPair{ .runtime = .classic, .development = null } }, + .{ "automatic", RuntimeDevelopmentPair{ .runtime = .automatic, .development = true } }, + .{ "react", RuntimeDevelopmentPair{ .runtime = .classic, .development = null } }, + .{ "react-jsx", RuntimeDevelopmentPair{ .runtime = .automatic, .development = true } }, + .{ "react-jsxdev", RuntimeDevelopmentPair{ .runtime = .automatic, .development = true } }, + .{ "solid", RuntimeDevelopmentPair{ .runtime = .solid, .development = null } }, }); pub const Pragma = struct { @@ -1013,6 +1018,10 @@ pub const JSX = struct { classic_import_source: string = "react", package_name: []const u8 = "react", + /// Configuration Priority: + /// - `--define=process.env.NODE_ENV=...` + /// - `NODE_ENV=...` + /// - tsconfig.json's `compilerOptions.jsx` (`react-jsx` or `react-jsxdev`) development: bool = true, parse: bool = true, @@ -1106,7 +1115,7 @@ pub const JSX = struct { // ...unless new is "React.createElement" and original is ["React", "createElement"] // saves an allocation for the majority case pub fn memberListToComponentsIfDifferent(allocator: std.mem.Allocator, original: []const string, new: string) ![]const string { - var splitter = std.mem.split(u8, new, "."); + var splitter = std.mem.splitScalar(u8, new, '.'); const count = strings.countChar(new, '.') + 1; var needs_alloc = false; @@ -1131,7 +1140,7 @@ pub const JSX = struct { var out = try allocator.alloc(string, count); - splitter = std.mem.split(u8, new, "."); + splitter = std.mem.splitScalar(u8, new, '.'); var i: usize = 0; while (splitter.next()) |str| { if (str.len == 0) continue; @@ -1575,13 +1584,27 @@ pub const BundleOptions = struct { supports_multiple_outputs: bool = true, + /// This is set by the process environment, which is used to override the + /// JSX configuration. When this is unspecified, the tsconfig.json is used + /// to determine if a development jsx-runtime is used (by going between + /// "react-jsx" or "react-jsx-dev-runtime") + force_node_env: ForceNodeEnv = .unspecified, + + pub const ForceNodeEnv = enum { + unspecified, + development, + production, + }; + pub fn isTest(this: *const BundleOptions) bool { return this.rewrite_jest_for_tests; } pub fn setProduction(this: *BundleOptions, value: bool) void { - this.production = value; - this.jsx.development = !value; + if (this.force_node_env == .unspecified) { + this.production = value; + this.jsx.development = !value; + } } pub const default_unwrap_commonjs_packages = [_]string{ diff --git a/src/output.zig b/src/output.zig index 3181b2788c1db3..5f793d4c7b670b 100644 --- a/src/output.zig +++ b/src/output.zig @@ -228,7 +228,7 @@ pub const Source = struct { }; pub const Stdio = struct { - extern "C" var bun_is_stdio_null: [3]i32; + extern "c" var bun_is_stdio_null: [3]i32; pub fn isStderrNull() bool { return bun_is_stdio_null[2] == 1; @@ -488,7 +488,7 @@ pub fn disableBuffering() void { } pub fn panic(comptime fmt: string, args: anytype) noreturn { - @setCold(true); + @branchHint(.cold); if (isEmojiEnabled()) { std.debug.panic(comptime prettyFmt(fmt, true), args); @@ -714,7 +714,7 @@ pub const LogFunction = fn (comptime fmt: string, args: anytype) callconv(bun.ca pub fn Scoped(comptime tag: anytype, comptime disabled: bool) type { const tagname = comptime brk: { const input = switch (@TypeOf(tag)) { - @Type(.EnumLiteral) => @tagName(tag), + @Type(.enum_literal) => @tagName(tag), else => tag, }; var ascii_slice: [input.len]u8 = undefined; @@ -1064,7 +1064,7 @@ pub inline fn err(error_name: anytype, comptime fmt: []const u8, args: anytype) const T = @TypeOf(error_name); const info = @typeInfo(T); - if (comptime T == bun.sys.Error or info == .Pointer and info.Pointer.child == bun.sys.Error) { + if (comptime T == bun.sys.Error or info == .pointer and info.pointer.child == bun.sys.Error) { const e: bun.sys.Error = error_name; const tag_name, const sys_errno = e.getErrorCodeTagName() orelse { err("unknown error", fmt, args); @@ -1081,10 +1081,10 @@ pub inline fn err(error_name: anytype, comptime fmt: []const u8, args: anytype) const display_name, const is_comptime_name = display_name: { // Zig string literals are of type *const [n:0]u8 // we assume that no one will pass this type from not using a string literal. - if (info == .Pointer and info.Pointer.size == .One and info.Pointer.is_const) { - const child_info = @typeInfo(info.Pointer.child); - if (child_info == .Array and child_info.Array.child == u8) { - if (child_info.Array.len == 0) @compileError("Output.err should not be passed an empty string (use errGeneric)"); + if (info == .pointer and info.pointer.size == .one and info.pointer.is_const) { + const child_info = @typeInfo(info.pointer.child); + if (child_info == .array and child_info.array.child == u8) { + if (child_info.array.len == 0) @compileError("Output.err should not be passed an empty string (use errGeneric)"); break :display_name .{ error_name, true }; } } @@ -1095,8 +1095,8 @@ pub inline fn err(error_name: anytype, comptime fmt: []const u8, args: anytype) } // error unions - if (info == .ErrorSet) { - if (info.ErrorSet) |errors| { + if (info == .error_set) { + if (info.error_set) |errors| { if (errors.len == 0) { @compileError("Output.err was given an empty error set"); } @@ -1109,7 +1109,7 @@ pub inline fn err(error_name: anytype, comptime fmt: []const u8, args: anytype) } // enum literals - if (info == .EnumLiteral) { + if (info == .enum_literal) { const tag = @tagName(info); comptime bun.assert(tag.len > 0); // how? if (tag[0] != 'E') break :display_name .{ "E" ++ tag, true }; @@ -1117,7 +1117,7 @@ pub inline fn err(error_name: anytype, comptime fmt: []const u8, args: anytype) } // enums - if (info == .Enum) { + if (info == .@"enum") { const errno: bun.C.SystemErrno = @enumFromInt(@intFromEnum(info)); break :display_name .{ @tagName(errno), false }; } diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index 21860d42a3b8d3..06a41db4a50452 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -28,9 +28,9 @@ pub const MacroImportReplacementMap = bun.StringArrayHashMap(string); pub const MacroMap = bun.StringArrayHashMapUnmanaged(MacroImportReplacementMap); const ScriptsMap = bun.StringArrayHashMap(string); -const Semver = @import("../install/semver.zig"); +const Semver = bun.Semver; const Dependency = @import("../install/dependency.zig"); -const String = @import("../install/semver.zig").String; +const String = Semver.String; const Version = Semver.Version; const Install = @import("../install/install.zig"); const FolderResolver = @import("../install/resolvers/folder_resolver.zig"); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 17875431c2899b..b714d33ace181c 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -43,7 +43,7 @@ const Install = @import("../install/install.zig"); const Lockfile = @import("../install/lockfile.zig").Lockfile; const Package = @import("../install/lockfile.zig").Package; const Resolution = @import("../install/resolution.zig").Resolution; -const Semver = @import("../install/semver.zig"); +const Semver = bun.Semver; const DotEnv = @import("../env_loader.zig"); pub fn isPackagePath(path: string) bool { @@ -341,17 +341,17 @@ pub const DebugLogs = struct { } pub fn increaseIndent(d: *DebugLogs) void { - @setCold(true); + @branchHint(.cold); d.indent.append(" ") catch unreachable; } pub fn decreaseIndent(d: *DebugLogs) void { - @setCold(true); + @branchHint(.cold); d.indent.list.shrinkRetainingCapacity(d.indent.list.items.len - 1); } pub fn addNote(d: *DebugLogs, _text: string) void { - @setCold(true); + @branchHint(.cold); var text = _text; const len = d.indent.len(); if (len > 0) { @@ -366,7 +366,7 @@ pub const DebugLogs = struct { } pub fn addNoteFmt(d: *DebugLogs, comptime fmt: string, args: anytype) void { - @setCold(true); + @branchHint(.cold); return d.addNote(std.fmt.allocPrint(d.notes.allocator, fmt, args) catch unreachable); } }; @@ -1338,7 +1338,42 @@ pub const Resolver = struct { } } - var source_dir_info = (r.dirInfoCached(source_dir) catch null) orelse return .{ .not_found = {} }; + var source_dir_info = r.dirInfoCached(source_dir) catch (return .{ .not_found = {} }) orelse dir: { + // It is possible to resolve with a source file that does not exist: + // A. Bundler plugin refers to a non-existing `resolveDir`. + // B. `createRequire()` is called with a path that does not exist. This was + // hit in Nuxt, specifically the `vite-node` dependency [1]. + // + // Normally it would make sense to always bail here, but in the case of + // resolving "hello" from "/project/nonexistent_dir/index.ts", resolution + // should still query "/project/node_modules" and "/node_modules" + // + // For case B in Node.js, they use `_resolveLookupPaths` in + // combination with `_nodeModulePaths` to collect a listing of + // all possible parent `node_modules` [2]. Bun has a much smarter + // approach that caches directory entries, but it (correctly) does + // not cache non-existing directories. To successfully resolve this, + // Bun finds the nearest existing directory, and uses that as the base + // for `node_modules` resolution. Since that directory entry knows how + // to resolve concrete node_modules, this iteration stops at the first + // existing directory, regardless of what it is. + // + // The resulting `source_dir_info` cannot resolve relative files. + // + // [1]: https://github.com/oven-sh/bun/issues/16705 + // [2]: https://github.com/nodejs/node/blob/e346323109b49fa6b9a4705f4e3816fc3a30c151/lib/internal/modules/cjs/loader.js#L1934 + if (Environment.allow_assert) + bun.assert(isPackagePath(import_path)); + var closest_dir = source_dir; + // Use std.fs.path.dirname to get `null` once the entire + // directory tree has been visited. `null` is theoretically + // impossible since the drive root should always exist. + while (std.fs.path.dirname(closest_dir)) |current| : (closest_dir = current) { + if (r.dirInfoCached(current) catch return .{ .not_found = {} }) |dir| + break :dir dir; + } + return .{ .not_found = {} }; + }; if (r.care_about_browser_field) { // Support remapping one package path to another via the "browser" field @@ -1804,6 +1839,22 @@ pub const Resolver = struct { dir_info = dir_info.getParent() orelse break; } + // try resolve from `NODE_PATH` + // https://nodejs.org/api/modules.html#loading-from-the-global-folders + const node_path: []const u8 = if (r.env_loader) |env_loader| env_loader.get("NODE_PATH") orelse "" else ""; + if (node_path.len > 0) { + var it = std.mem.tokenizeScalar(u8, node_path, if (Environment.isWindows) ';' else ':'); + while (it.next()) |path| { + const abs_path = r.fs.absBuf(&[_]string{ path, import_path }, bufs(.node_modules_check)); + if (r.debug_logs) |*debug| { + debug.addNoteFmt("Checking for a package in the NODE_PATH directory \"{s}\"", .{abs_path}); + } + if (r.loadAsFileOrDirectory(abs_path, kind)) |res| { + return .{ .success = res }; + } + } + } + dir_info = source_dir_info; // this is the magic! @@ -1815,7 +1866,7 @@ pub const Resolver = struct { // check the global cache directory for a package.json file. const manager = r.getPackageManager(); var dependency_version = Dependency.Version{}; - var dependency_behavior = Dependency.Behavior.prod; + var dependency_behavior: Dependency.Behavior = .{ .prod = true }; var string_buf = esm.version; // const initial_pending_tasks = manager.pending_tasks; @@ -2077,8 +2128,6 @@ pub const Resolver = struct { } } - // Mostly to cut scope, we don't resolve `NODE_PATH` environment variable. - // But also: https://github.com/nodejs/node/issues/38128#issuecomment-814969356 return .{ .not_found = {} }; } fn dirInfoForResolution( @@ -3313,7 +3362,7 @@ pub const Resolver = struct { comptime { const Resolver__nodeModulePathsForJS = JSC.toJSHostFunction(Resolver__nodeModulePathsForJS_); - @export(Resolver__nodeModulePathsForJS, .{ .name = "Resolver__nodeModulePathsForJS" }); + @export(&Resolver__nodeModulePathsForJS, .{ .name = "Resolver__nodeModulePathsForJS" }); } pub fn Resolver__nodeModulePathsForJS_(globalThis: *bun.JSC.JSGlobalObject, callframe: *bun.JSC.CallFrame) bun.JSError!JSC.JSValue { bun.JSC.markBinding(@src()); @@ -3332,7 +3381,7 @@ pub const Resolver = struct { pub export fn Resolver__propForRequireMainPaths(globalThis: *bun.JSC.JSGlobalObject) callconv(.C) JSC.JSValue { bun.JSC.markBinding(@src()); - const in_str = bun.String.createUTF8("."); + const in_str = bun.String.init("."); const r = &globalThis.bunVM().transpiler.resolver; return nodeModulePathsJSValue(r, in_str, globalThis); } @@ -4237,9 +4286,7 @@ pub const GlobalCache = enum { }; comptime { - if (!bun.JSC.is_bindgen) { - _ = Resolver.Resolver__propForRequireMainPaths; - } + _ = Resolver.Resolver__propForRequireMainPaths; } const assert = bun.assert; diff --git a/src/resolver/tsconfig_json.zig b/src/resolver/tsconfig_json.zig index c4e40a70569ef4..2da0564e736a29 100644 --- a/src/resolver/tsconfig_json.zig +++ b/src/resolver/tsconfig_json.zig @@ -216,12 +216,14 @@ pub const TSConfigJSON = struct { defer allocator.free(str_lower); _ = strings.copyLowercase(str, str_lower); // - We don't support "preserve" yet - // - We rely on NODE_ENV for "jsx" or "jsxDEV" - // - We treat "react-jsx" and "react-jsxDEV" identically - // because it is too easy to auto-import the wrong one. if (options.JSX.RuntimeMap.get(str_lower)) |runtime| { - result.jsx.runtime = runtime; + result.jsx.runtime = runtime.runtime; result.jsx_flags.insert(.runtime); + + if (runtime.development) |dev| { + result.jsx.development = dev; + result.jsx_flags.insert(.development); + } } } } @@ -424,7 +426,7 @@ pub const TSConfigJSON = struct { return parts.items; } - var iter = std.mem.tokenize(u8, text, "."); + var iter = std.mem.tokenizeScalar(u8, text, '.'); while (iter.next()) |part| { if (!js_lexer.isIdentifier(part)) { diff --git a/src/s3/client.zig b/src/s3/client.zig index 6d527ff9f2afa0..a5f9fdfd424a53 100644 --- a/src/s3/client.zig +++ b/src/s3/client.zig @@ -202,7 +202,7 @@ const S3UploadStreamWrapper = struct { callback_context: *anyopaque, ref_count: u32 = 1, path: []const u8, // this is owned by the task not by the wrapper - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub fn resolve(result: S3UploadResult, self: *@This()) void { const sink = self.sink; defer self.deref(); @@ -282,9 +282,9 @@ pub const Export = shim.exportFunctions(.{ }); comptime { const jsonResolveRequestStream = JSC.toJSHostFunction(onUploadStreamResolveRequestStream); - @export(jsonResolveRequestStream, .{ .name = Export[0].symbol_name }); + @export(&jsonResolveRequestStream, .{ .name = Export[0].symbol_name }); const jsonRejectRequestStream = JSC.toJSHostFunction(onUploadStreamRejectRequestStream); - @export(jsonRejectRequestStream, .{ .name = Export[1].symbol_name }); + @export(&jsonRejectRequestStream, .{ .name = Export[1].symbol_name }); } /// consumes the readable stream and upload to s3 diff --git a/src/s3/credentials.zig b/src/s3/credentials.zig index fdf2a45c3d43d7..a8701f335354b6 100644 --- a/src/s3/credentials.zig +++ b/src/s3/credentials.zig @@ -23,7 +23,7 @@ pub const S3Credentials = struct { insecure_http: bool = false, ref_count: u32 = 1, - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); pub fn estimatedSize(this: *const @This()) usize { return @sizeOf(S3Credentials) + this.accessKeyId.len + this.region.len + this.secretAccessKey.len + this.endpoint.len + this.bucket.len; @@ -45,6 +45,7 @@ pub const S3Credentials = struct { return hasher.final(); } pub fn getCredentialsWithOptions(this: S3Credentials, default_options: MultiPartUploadOptions, options: ?JSC.JSValue, default_acl: ?ACL, default_storage_class: ?StorageClass, globalObject: *JSC.JSGlobalObject) bun.JSError!S3CredentialsWithOptions { + bun.analytics.Features.s3 += 1; // get ENV config var new_credentials = S3CredentialsWithOptions{ .credentials = this, diff --git a/src/s3/multipart.zig b/src/s3/multipart.zig index 3dbadac73f9232..5fa8502cd7f375 100644 --- a/src/s3/multipart.zig +++ b/src/s3/multipart.zig @@ -9,7 +9,96 @@ const MultiPartUploadOptions = @import("./multipart_options.zig").MultiPartUploa const S3SimpleRequest = @import("./simple_request.zig"); const executeSimpleS3Request = S3SimpleRequest.executeSimpleS3Request; const S3Error = @import("./error.zig").S3Error; - +// When we start the request we will buffer data until partSize is reached or the last chunk is received. +// If the buffer is smaller than partSize, it will be sent as a single request. Otherwise, a multipart upload will be initiated. +// If we send a single request it will retry until the maximum retry count is reached. The single request do not increase the reference count of MultiPartUpload, as they are the final step. +// When sending a multipart upload, if there is space in the queue, the part is enqueued, and the request starts immediately. +// If the queue is full, it waits to be drained before starting a new part request. +// Each part maintains a reference to MultiPartUpload until completion. +// If a part is canceled or fails early, the allocated slice is freed, and the reference is removed. If a part completes successfully, an etag is received, the allocated slice is deallocated, and the etag is appended to multipart_etags. If a part request fails, it retries until the maximum retry count is reached. If it still fails, MultiPartUpload is marked as failed and its reference is removed. +// If all parts succeed, a complete request is sent. +// If any part fails, a rollback request deletes the uploaded parts. Rollback and commit requests do not increase the reference count of MultiPartUpload, as they are the final step. Once commit or rollback finishes, the reference count is decremented, and MultiPartUpload is freed. These requests retry up to the maximum retry count on a best-effort basis. + +// Start Upload +// │ +// ▼ +// Buffer Incoming Data +// │ +// │ +// ┌────────────┴────────────────┐ +// │ │ +// ▼ ▼ +// Buffer < PartSize Buffer >= PartSize +// and is Last Chunk │ +// │ │ +// │ │ +// │ │ +// │ │ +// │ ▼ +// │ Start Multipart Upload +// │ │ +// │ Initialize Parts Queue +// │ │ +// │ Process Upload Parts +// │ │ +// │ ┌──────────┴──────────┐ +// │ │ │ +// │ ▼ ▼ +// │ Queue Has Space Queue Full +// │ │ │ +// │ │ ▼ +// │ │ Wait for Queue +// │ │ │ +// │ └──────────┬──────────┘ +// │ │ +// │ ▼ +// │ Start Part Upload +// │ (Reference MultiPartUpload) +// │ │ +// │ ┌─────────┼─────────┐ +// │ │ │ │ +// │ ▼ ▼ ▼ +// │ Part Success Failure +// │ Canceled │ │ +// │ │ │ Retry Part +// │ │ │ │ +// │ Free Free Max Retries? +// │ Slice Slice │ │ +// │ │ │ No Yes +// │ Deref Add eTag │ │ +// │ MPU to Array │ Fail MPU +// │ │ │ │ │ +// │ │ │ │ Deref MPU +// │ └─────────┼──────┘ │ +// │ │ │ +// │ ▼ │ +// │ All Parts Complete? │ +// │ │ │ +// │ ┌───────┴───────┐ │ +// │ │ │ │ +// │ ▼ ▼ │ +// │ All Success Some Failed │ +// │ │ │ │ +// │ ▼ ▼ │ +// │ Send Commit Send Rollback │ +// │ (No Ref Inc) (No Ref Inc) │ +// │ │ │ │ +// │ └───────┬───────┘ │ +// │ │ │ +// │ ▼ │ +// │ Retry if Failed │ +// │ (Best Effort Only) │ +// │ │ │ +// │ ▼ │ +// │ Deref Final MPU │ +// │ │ │ +// ▼ │ │ +// Single Upload Request │ │ +// │ │ │ +// └────────────────────────────┴───────────────┘ +// │ +// ▼ +// End pub const MultiPartUpload = struct { const OneMiB: usize = MultiPartUploadOptions.OneMiB; const MAX_SINGLE_UPLOAD_SIZE: usize = MultiPartUploadOptions.MAX_SINGLE_UPLOAD_SIZE; // we limit to 5 GiB @@ -17,7 +106,7 @@ pub const MultiPartUpload = struct { const DefaultPartSize = MultiPartUploadOptions.DefaultPartSize; const MAX_QUEUE_SIZE = MultiPartUploadOptions.MAX_QUEUE_SIZE; const AWS = S3Credentials; - queue: std.ArrayListUnmanaged(UploadPart) = .{}, + queue: ?[]UploadPart = null, available: bun.bit_set.IntegerBitSet(MAX_QUEUE_SIZE) = bun.bit_set.IntegerBitSet(MAX_QUEUE_SIZE).initFull(), currentPartNumber: u16 = 1, @@ -56,7 +145,7 @@ pub const MultiPartUpload = struct { callback: *const fn (S3SimpleRequest.S3UploadResult, *anyopaque) void, callback_context: *anyopaque, - pub usingnamespace bun.NewRefCounted(@This(), @This().deinit); + pub usingnamespace bun.NewRefCounted(@This(), deinit, null); const log = bun.Output.scoped(.S3MultiPartUpload, true); @@ -64,11 +153,12 @@ pub const MultiPartUpload = struct { data: []const u8, ctx: *MultiPartUpload, allocated_size: usize, - state: enum { - pending, - started, - completed, - canceled, + state: enum(u8) { + not_assigned = 0, + pending = 1, + started = 2, + completed = 3, + canceled = 4, }, partNumber: u16, // max is 10,000 retry: u8, // auto retry, decrement until 0 and fail after this @@ -78,6 +168,7 @@ pub const MultiPartUpload = struct { number: u16, etag: []const u8, }; + fn sortEtags(_: *MultiPartUpload, a: UploadPart.UploadPartResult, b: UploadPart.UploadPartResult) bool { return a.number < b.number; } @@ -117,6 +208,7 @@ pub const MultiPartUpload = struct { this.perform(); return; } else { + this.state = .not_assigned; log("onPartResponse {} failed", .{this.partNumber}); this.freeAllocatedSlice(); defer this.ctx.deref(); @@ -131,7 +223,7 @@ pub const MultiPartUpload = struct { .number = this.partNumber, .etag = bun.default_allocator.dupe(u8, etag) catch bun.outOfMemory(), }) catch bun.outOfMemory(); - + this.state = .not_assigned; defer this.ctx.deref(); // mark as available this.ctx.available.set(this.index); @@ -156,7 +248,7 @@ pub const MultiPartUpload = struct { }, .{ .part = @ptrCast(&onPartResponse) }, this); } pub fn start(this: *@This()) void { - if (this.state != .pending or this.ctx.state != .multipart_completed or this.ctx.state == .finished) return; + if (this.state != .pending or this.ctx.state != .multipart_completed) return; this.ctx.ref(); this.state = .started; this.perform(); @@ -177,8 +269,10 @@ pub const MultiPartUpload = struct { fn deinit(this: *@This()) void { log("deinit", .{}); - if (this.queue.capacity > 0) - this.queue.deinit(bun.default_allocator); + if (this.queue) |queue| { + this.queue = null; + bun.default_allocator.free(queue); + } this.poll_ref.unref(this.vm); bun.default_allocator.free(this.path); if (this.proxy.len > 0) { @@ -202,15 +296,12 @@ pub const MultiPartUpload = struct { } pub fn singleSendUploadResponse(result: S3SimpleRequest.S3UploadResult, this: *@This()) void { - defer this.deref(); if (this.state == .finished) return; switch (result) { .failure => |err| { if (this.options.retry > 0) { log("singleSendUploadResponse {} retry", .{this.options.retry}); this.options.retry -= 1; - this.ref(); - // retry failed executeSimpleS3Request(this.credentials, .{ .path = this.path, .method = .PUT, @@ -234,33 +325,40 @@ pub const MultiPartUpload = struct { } } + /// This is the only place we allocate the queue or the parts, this is responsible for the flow of parts and the max allowed concurrency fn getCreatePart(this: *@This(), chunk: []const u8, allocated_size: usize, needs_clone: bool) ?*UploadPart { const index = this.available.findFirstSet() orelse { // this means that the queue is full and we cannot flush it return null; }; - - if (index >= this.options.queueSize) { + const queueSize = this.options.queueSize; + if (index >= queueSize) { // ops too much concurrency wait more return null; } this.available.unset(index); defer this.currentPartNumber += 1; - const data = if (needs_clone) bun.default_allocator.dupe(u8, chunk) catch bun.outOfMemory() else chunk; - const allocated_len = if (needs_clone) data.len else allocated_size; - if (this.queue.items.len <= index) { - this.queue.append(bun.default_allocator, .{ - .data = data, - .allocated_size = allocated_len, - .partNumber = this.currentPartNumber, + if (this.queue == null) { + // queueSize will never change and is small (max 255) + const queue = bun.default_allocator.alloc(UploadPart, queueSize) catch bun.outOfMemory(); + // zero set just in case + @memset(queue, UploadPart{ + .data = "", + .allocated_size = 0, + .partNumber = 0, .ctx = this, - .index = @truncate(index), - .retry = this.options.retry, - .state = .pending, - }) catch bun.outOfMemory(); - return &this.queue.items[index]; + .index = 0, + .retry = 0, + .state = .not_assigned, + }); + this.queue = queue; } - this.queue.items[index] = .{ + const data = if (needs_clone) bun.default_allocator.dupe(u8, chunk) catch bun.outOfMemory() else chunk; + const allocated_len = if (needs_clone) data.len else allocated_size; + + const queue_item = &this.queue.?[index]; + // always set all struct fields to avoid undefined behavior + queue_item.* = .{ .data = data, .allocated_size = allocated_len, .partNumber = this.currentPartNumber, @@ -269,19 +367,22 @@ pub const MultiPartUpload = struct { .retry = this.options.retry, .state = .pending, }; - return &this.queue.items[index]; + return queue_item; } + /// Drain the parts, this is responsible for starting the parts and processing the buffered data fn drainEnqueuedParts(this: *@This()) void { - if (this.state == .finished) { + if (this.state == .finished or this.state == .singlefile_started) { return; } // check pending to start or transformed buffered ones into tasks if (this.state == .multipart_completed) { - for (this.queue.items) |*part| { - if (part.state == .pending) { - // lets start the part request - part.start(); + if (this.queue) |queue| { + for (queue) |*part| { + if (part.state == .pending) { + // lets start the part request + part.start(); + } } } } @@ -291,15 +392,20 @@ pub const MultiPartUpload = struct { } if (this.ended and this.available.mask == std.bit_set.IntegerBitSet(MAX_QUEUE_SIZE).initFull().mask) { - // we are done + // we are done and no more parts are running this.done(); } } + /// Finalize the upload with a failure pub fn fail(this: *@This(), _err: S3Error) void { log("fail {s}:{s}", .{ _err.code, _err.message }); this.ended = true; - for (this.queue.items) |*task| { - task.cancel(); + if (this.queue) |queue| { + for (queue) |*task| { + if (task.state != .not_assigned) { + task.cancel(); + } + } } if (this.state != .finished) { const old_state = this.state; @@ -307,19 +413,23 @@ pub const MultiPartUpload = struct { this.callback(.{ .failure = _err }, this.callback_context); if (old_state == .multipart_completed) { + // we are a multipart upload so we need to rollback // will deref after rollback this.rollbackMultiPartRequest(); } else { + // single file upload no need to rollback this.deref(); } } } - + /// Finalize successful the upload fn done(this: *@This()) void { if (this.state == .multipart_completed) { + // we are a multipart upload so we need to send the etags and commit this.state = .finished; - + // sort the etags std.sort.block(UploadPart.UploadPartResult, this.multipart_etags.items, this, UploadPart.sortEtags); + // start the multipart upload list this.multipart_upload_list.append(bun.default_allocator, "") catch bun.outOfMemory(); for (this.multipart_etags.items) |tag| { this.multipart_upload_list.appendFmt(bun.default_allocator, "{}{s}", .{ tag.number, tag.etag }) catch bun.outOfMemory(); @@ -332,11 +442,14 @@ pub const MultiPartUpload = struct { // will deref and ends after commit this.commitMultiPartRequest(); } else { + // single file upload no need to commit this.callback(.{ .success = {} }, this.callback_context); this.state = .finished; this.deref(); } } + + /// Result of the Multipart request, after this we can start draining the parts pub fn startMultiPartRequestResult(result: S3SimpleRequest.S3DownloadResult, this: *@This()) void { defer this.deref(); if (this.state == .finished) return; @@ -365,6 +478,7 @@ pub const MultiPartUpload = struct { } log("startMultiPartRequestResult {s} success id: {s}", .{ this.path, this.upload_id }); this.state = .multipart_completed; + // start draining the parts this.drainEnqueuedParts(); }, // this is "unreachable" but we cover in case AWS returns 404 @@ -375,6 +489,7 @@ pub const MultiPartUpload = struct { } } + /// We do a best effort to commit the multipart upload, if it fails we will retry, if it still fails we will fail the upload pub fn onCommitMultiPartRequest(result: S3SimpleRequest.S3CommitResult, this: *@This()) void { log("onCommitMultiPartRequest {s}", .{this.upload_id}); @@ -396,7 +511,7 @@ pub const MultiPartUpload = struct { }, } } - + /// We do a best effort to rollback the multipart upload, if it fails we will retry, if it still we just deinit the upload pub fn onRollbackMultiPartRequest(result: S3SimpleRequest.S3UploadResult, this: *@This()) void { log("onRollbackMultiPartRequest {s}", .{this.upload_id}); switch (result) { @@ -527,7 +642,6 @@ pub const MultiPartUpload = struct { if (this.ended and this.buffered.items.len < this.partSizeInBytes() and this.state == .not_started) { log("processBuffered {s} singlefile_started", .{this.path}); this.state = .singlefile_started; - this.ref(); // we can do only 1 request executeSimpleS3Request(this.credentials, .{ .path = this.path, diff --git a/src/semver.zig b/src/semver.zig new file mode 100644 index 00000000000000..43b85e34072eee --- /dev/null +++ b/src/semver.zig @@ -0,0 +1,9 @@ +// These are all extern so they can't be top-level structs. +pub const String = @import("./semver/SemverString.zig").String; +pub const ExternalString = @import("./semver/ExternalString.zig").ExternalString; +pub const Version = @import("./semver/Version.zig").Version; + +pub const SlicedString = @import("./semver/SlicedString.zig"); +pub const Range = @import("./semver/SemverRange.zig"); +pub const Query = @import("./semver/SemverQuery.zig"); +pub const SemverObject = @import("./semver/SemverObject.zig"); diff --git a/src/semver/ExternalString.zig b/src/semver/ExternalString.zig new file mode 100644 index 00000000000000..a389a401dcb963 --- /dev/null +++ b/src/semver/ExternalString.zig @@ -0,0 +1,66 @@ +pub const ExternalString = extern struct { + value: String = String{}, + hash: u64 = 0, + + pub inline fn fmt(this: *const ExternalString, buf: []const u8) String.Formatter { + return this.value.fmt(buf); + } + + pub fn order(lhs: *const ExternalString, rhs: *const ExternalString, lhs_buf: []const u8, rhs_buf: []const u8) std.math.Order { + if (lhs.hash == rhs.hash and lhs.hash > 0) return .eq; + + return lhs.value.order(&rhs.value, lhs_buf, rhs_buf); + } + + /// ExternalString but without the hash + pub inline fn from(in: string) ExternalString { + return ExternalString{ + .value = String.init(in, in), + .hash = bun.Wyhash.hash(0, in), + }; + } + + pub inline fn isInline(this: ExternalString) bool { + return this.value.isInline(); + } + + pub inline fn isEmpty(this: ExternalString) bool { + return this.value.isEmpty(); + } + + pub inline fn len(this: ExternalString) usize { + return this.value.len(); + } + + pub inline fn init(buf: string, in: string, hash: u64) ExternalString { + return ExternalString{ + .value = String.init(buf, in), + .hash = hash, + }; + } + + pub inline fn slice(this: *const ExternalString, buf: string) string { + return this.value.slice(buf); + } +}; + +const assert = bun.assert; +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = bun.IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const SlicedString = bun.Semver.SlicedString; +const String = bun.Semver.String; diff --git a/src/semver/SemverObject.zig b/src/semver/SemverObject.zig new file mode 100644 index 00000000000000..6c0ccf6dbb18c5 --- /dev/null +++ b/src/semver/SemverObject.zig @@ -0,0 +1,152 @@ +pub fn create(globalThis: *JSC.JSGlobalObject) JSC.JSValue { + const object = JSC.JSValue.createEmptyObject(globalThis, 2); + + object.put( + globalThis, + JSC.ZigString.static("satisfies"), + JSC.NewFunction( + globalThis, + JSC.ZigString.static("satisfies"), + 2, + SemverObject.satisfies, + false, + ), + ); + + object.put( + globalThis, + JSC.ZigString.static("order"), + JSC.NewFunction( + globalThis, + JSC.ZigString.static("order"), + 2, + SemverObject.order, + false, + ), + ); + + return object; +} + +pub fn order( + globalThis: *JSC.JSGlobalObject, + callFrame: *JSC.CallFrame, +) bun.JSError!JSC.JSValue { + var arena = std.heap.ArenaAllocator.init(bun.default_allocator); + defer arena.deinit(); + var stack_fallback = std.heap.stackFallback(512, arena.allocator()); + const allocator = stack_fallback.get(); + + const arguments = callFrame.arguments_old(2).slice(); + if (arguments.len < 2) { + return globalThis.throw("Expected two arguments", .{}); + } + + const left_arg = arguments[0]; + const right_arg = arguments[1]; + + const left_string = left_arg.toStringOrNull(globalThis) orelse return JSC.jsNumber(0); + const right_string = right_arg.toStringOrNull(globalThis) orelse return JSC.jsNumber(0); + + const left = left_string.toSlice(globalThis, allocator); + defer left.deinit(); + const right = right_string.toSlice(globalThis, allocator); + defer right.deinit(); + + if (!strings.isAllASCII(left.slice())) return JSC.jsNumber(0); + if (!strings.isAllASCII(right.slice())) return JSC.jsNumber(0); + + const left_result = Version.parse(SlicedString.init(left.slice(), left.slice())); + const right_result = Version.parse(SlicedString.init(right.slice(), right.slice())); + + if (!left_result.valid) { + return globalThis.throw("Invalid SemVer: {s}\n", .{left.slice()}); + } + + if (!right_result.valid) { + return globalThis.throw("Invalid SemVer: {s}\n", .{right.slice()}); + } + + const left_version = left_result.version.max(); + const right_version = right_result.version.max(); + + return switch (left_version.orderWithoutBuild(right_version, left.slice(), right.slice())) { + .eq => JSC.jsNumber(0), + .gt => JSC.jsNumber(1), + .lt => JSC.jsNumber(-1), + }; +} + +pub fn satisfies(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!JSC.JSValue { + var arena = std.heap.ArenaAllocator.init(bun.default_allocator); + defer arena.deinit(); + var stack_fallback = std.heap.stackFallback(512, arena.allocator()); + const allocator = stack_fallback.get(); + + const arguments = callFrame.arguments_old(2).slice(); + if (arguments.len < 2) { + return globalThis.throw("Expected two arguments", .{}); + } + + const left_arg = arguments[0]; + const right_arg = arguments[1]; + + const left_string = left_arg.toStringOrNull(globalThis) orelse return .zero; + const right_string = right_arg.toStringOrNull(globalThis) orelse return .zero; + + const left = left_string.toSlice(globalThis, allocator); + defer left.deinit(); + const right = right_string.toSlice(globalThis, allocator); + defer right.deinit(); + + if (!strings.isAllASCII(left.slice())) return .false; + if (!strings.isAllASCII(right.slice())) return .false; + + const left_result = Version.parse(SlicedString.init(left.slice(), left.slice())); + if (left_result.wildcard != .none) { + return .false; + } + + const left_version = left_result.version.min(); + + const right_group = try Query.parse( + allocator, + right.slice(), + SlicedString.init(right.slice(), right.slice()), + ); + defer right_group.deinit(); + + const right_version = right_group.getExactVersion(); + + if (right_version != null) { + return JSC.jsBoolean(left_version.eql(right_version.?)); + } + + return JSC.jsBoolean(right_group.satisfies(left_version, right.slice(), left.slice())); +} + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = @import("../identity_context.zig").IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const ExternalString = bun.Semver.ExternalString; +const SlicedString = bun.Semver.SlicedString; +const String = bun.Semver.String; + +const Query = bun.Semver.Query; +const assert = bun.assert; +const Version = bun.Semver.Version; +const SemverObject = @This(); diff --git a/src/semver/SemverQuery.zig b/src/semver/SemverQuery.zig new file mode 100644 index 00000000000000..55a7772578cabd --- /dev/null +++ b/src/semver/SemverQuery.zig @@ -0,0 +1,801 @@ +/// Linked-list of AND ranges +/// "^1 ^2" +/// ----|----- +/// That is two Query +pub const Op = enum { + none, + AND, + OR, +}; + +range: Range = Range{}, + +// AND +next: ?*Query = null, + +const Formatter = struct { + query: *const Query, + buffer: []const u8, + pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const this = formatter.query; + + if (this.next) |ptr| { + if (ptr.range.hasLeft() or ptr.range.hasRight()) { + try std.fmt.format(writer, "{} && {}", .{ this.range.fmt(formatter.buffer), ptr.range.fmt(formatter.buffer) }); + return; + } + } + + try std.fmt.format(writer, "{}", .{this.range.fmt(formatter.buffer)}); + } +}; + +pub fn fmt(this: *const Query, buf: []const u8) @This().Formatter { + return .{ .query = this, .buffer = buf }; +} + +/// Linked-list of Queries OR'd together +/// "^1 || ^2" +/// ----|----- +/// That is two List +pub const List = struct { + head: Query = Query{}, + tail: ?*Query = null, + + // OR + next: ?*List = null, + + const Formatter = struct { + list: *const List, + buffer: []const u8, + pub fn format(formatter: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const this = formatter.list; + + if (this.next) |ptr| { + try std.fmt.format(writer, "{} || {}", .{ this.head.fmt(formatter.buffer), ptr.fmt(formatter.buffer) }); + } else { + try std.fmt.format(writer, "{}", .{this.head.fmt(formatter.buffer)}); + } + } + }; + + pub fn fmt(this: *const List, buf: []const u8) @This().Formatter { + return .{ .list = this, .buffer = buf }; + } + + pub fn satisfies(list: *const List, version: Version, list_buf: string, version_buf: string) bool { + return list.head.satisfies( + version, + list_buf, + version_buf, + ) or (list.next orelse return false).satisfies( + version, + list_buf, + version_buf, + ); + } + + pub fn satisfiesPre(list: *const List, version: Version, list_buf: string, version_buf: string) bool { + if (comptime Environment.allow_assert) { + assert(version.tag.hasPre()); + } + + // `version` has a prerelease tag: + // - needs to satisfy each comparator in the query ( AND AND ...) like normal comparison + // - if it does, also needs to match major, minor, patch with at least one of the other versions + // with a prerelease + // https://github.com/npm/node-semver/blob/ac9b35769ab0ddfefd5a3af4a3ecaf3da2012352/classes/range.js#L505 + var pre_matched = false; + return (list.head.satisfiesPre( + version, + list_buf, + version_buf, + &pre_matched, + ) and pre_matched) or (list.next orelse return false).satisfiesPre( + version, + list_buf, + version_buf, + ); + } + + pub fn eql(lhs: *const List, rhs: *const List) bool { + if (!lhs.head.eql(&rhs.head)) return false; + + const lhs_next = lhs.next orelse return rhs.next == null; + const rhs_next = rhs.next orelse return false; + + return lhs_next.eql(rhs_next); + } + + pub fn andRange(self: *List, allocator: Allocator, range: Range) !void { + if (!self.head.range.hasLeft() and !self.head.range.hasRight()) { + self.head.range = range; + return; + } + + var tail = try allocator.create(Query); + tail.* = Query{ + .range = range, + }; + tail.range = range; + + var last_tail = self.tail orelse &self.head; + last_tail.next = tail; + self.tail = tail; + } +}; + +pub const Group = struct { + head: List = List{}, + tail: ?*List = null, + allocator: Allocator, + input: string = "", + + flags: FlagsBitSet = FlagsBitSet.initEmpty(), + pub const Flags = struct { + pub const pre = 1; + pub const build = 0; + }; + + const Formatter = struct { + group: *const Group, + buf: string, + + pub fn format(formatter: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const this = formatter.group; + + if (this.tail == null and this.head.tail == null and !this.head.head.range.hasLeft()) { + return; + } + + if (this.tail == null and this.head.tail == null) { + try std.fmt.format(writer, "{}", .{this.head.fmt(formatter.buf)}); + return; + } + + var list = &this.head; + while (list.next) |next| { + try std.fmt.format(writer, "{} && ", .{list.fmt(formatter.buf)}); + list = next; + } + + try std.fmt.format(writer, "{}", .{list.fmt(formatter.buf)}); + } + }; + + pub fn fmt(this: *const Group, buf: string) @This().Formatter { + return .{ + .group = this, + .buf = buf, + }; + } + + pub fn jsonStringify(this: *const Group, writer: anytype) !void { + const temp = try std.fmt.allocPrint(bun.default_allocator, "{}", .{this.fmt()}); + defer bun.default_allocator.free(temp); + try std.json.encodeJsonString(temp, .{}, writer); + } + + pub fn deinit(this: *const Group) void { + var list = this.head; + var allocator = this.allocator; + + while (list.next) |next| { + var query = list.head; + while (query.next) |next_query| { + query = next_query.*; + allocator.destroy(next_query); + } + list = next.*; + allocator.destroy(next); + } + } + + pub fn getExactVersion(this: *const Group) ?Version { + const range = this.head.head.range; + if (this.head.next == null and + this.head.head.next == null and + range.hasLeft() and + range.left.op == .eql and + !range.hasRight()) + { + if (comptime Environment.allow_assert) { + assert(this.tail == null); + } + return range.left.version; + } + + return null; + } + + pub fn from(version: Version) Group { + return .{ + .allocator = bun.default_allocator, + .head = .{ + .head = .{ + .range = .{ + .left = .{ + .op = .eql, + .version = version, + }, + }, + }, + }, + }; + } + + pub const FlagsBitSet = bun.bit_set.IntegerBitSet(3); + + pub fn isExact(this: *const Group) bool { + return this.head.next == null and this.head.head.next == null and !this.head.head.range.hasRight() and this.head.head.range.left.op == .eql; + } + + pub fn @"is *"(this: *const Group) bool { + const left = this.head.head.range.left; + return this.head.head.range.right.op == .unset and + left.op == .gte and + this.head.next == null and + this.head.head.next == null and + left.version.isZero() and + !this.flags.isSet(Flags.build); + } + + pub inline fn eql(lhs: Group, rhs: Group) bool { + return lhs.head.eql(&rhs.head); + } + + pub fn toVersion(this: Group) Version { + assert(this.isExact() or this.head.head.range.left.op == .unset); + return this.head.head.range.left.version; + } + + pub fn orVersion(self: *Group, version: Version) !void { + if (self.tail == null and !self.head.head.range.hasLeft()) { + self.head.head.range.left.version = version; + self.head.head.range.left.op = .eql; + return; + } + + var new_tail = try self.allocator.create(List); + new_tail.* = List{}; + new_tail.head.range.left.version = version; + new_tail.head.range.left.op = .eql; + + var prev_tail = self.tail orelse &self.head; + prev_tail.next = new_tail; + self.tail = new_tail; + } + + pub fn andRange(self: *Group, range: Range) !void { + var tail = self.tail orelse &self.head; + try tail.andRange(self.allocator, range); + } + + pub fn orRange(self: *Group, range: Range) !void { + if (self.tail == null and self.head.tail == null and !self.head.head.range.hasLeft()) { + self.head.head.range = range; + return; + } + + var new_tail = try self.allocator.create(List); + new_tail.* = List{}; + new_tail.head.range = range; + + var prev_tail = self.tail orelse &self.head; + prev_tail.next = new_tail; + self.tail = new_tail; + } + + pub inline fn satisfies( + group: *const Group, + version: Version, + group_buf: string, + version_buf: string, + ) bool { + return if (version.tag.hasPre()) + group.head.satisfiesPre(version, group_buf, version_buf) + else + group.head.satisfies(version, group_buf, version_buf); + } +}; + +pub fn eql(lhs: *const Query, rhs: *const Query) bool { + if (!lhs.range.eql(rhs.range)) return false; + + const lhs_next = lhs.next orelse return rhs.next == null; + const rhs_next = rhs.next orelse return false; + + return lhs_next.eql(rhs_next); +} + +pub fn satisfies(query: *const Query, version: Version, query_buf: string, version_buf: string) bool { + return query.range.satisfies( + version, + query_buf, + version_buf, + ) and (query.next orelse return true).satisfies( + version, + query_buf, + version_buf, + ); +} + +pub fn satisfiesPre(query: *const Query, version: Version, query_buf: string, version_buf: string, pre_matched: *bool) bool { + if (comptime Environment.allow_assert) { + assert(version.tag.hasPre()); + } + return query.range.satisfiesPre( + version, + query_buf, + version_buf, + pre_matched, + ) and (query.next orelse return true).satisfiesPre( + version, + query_buf, + version_buf, + pre_matched, + ); +} + +pub const Token = struct { + tag: Tag = Tag.none, + wildcard: Wildcard = Wildcard.none, + + pub fn toRange(this: Token, version: Version.Partial) Range { + switch (this.tag) { + // Allows changes that do not modify the left-most non-zero element in the [major, minor, patch] tuple + .caret => { + // https://github.com/npm/node-semver/blob/3a8a4309ae986c1967b3073ba88c9e69433d44cb/classes/range.js#L302-L353 + var range = Range{}; + if (version.major) |major| done: { + range.left = .{ + .op = .gte, + .version = .{ + .major = major, + }, + }; + range.right = .{ + .op = .lt, + }; + if (version.minor) |minor| { + range.left.version.minor = minor; + if (version.patch) |patch| { + range.left.version.patch = patch; + range.left.version.tag = version.tag; + if (major == 0) { + if (minor == 0) { + range.right.version.patch = patch +| 1; + } else { + range.right.version.minor = minor +| 1; + } + break :done; + } + } else if (major == 0) { + range.right.version.minor = minor +| 1; + break :done; + } + } + range.right.version.major = major +| 1; + } + return range; + }, + .tilda => { + // https://github.com/npm/node-semver/blob/3a8a4309ae986c1967b3073ba88c9e69433d44cb/classes/range.js#L261-L287 + var range = Range{}; + if (version.major) |major| done: { + range.left = .{ + .op = .gte, + .version = .{ + .major = major, + }, + }; + range.right = .{ + .op = .lt, + }; + if (version.minor) |minor| { + range.left.version.minor = minor; + if (version.patch) |patch| { + range.left.version.patch = patch; + range.left.version.tag = version.tag; + } + range.right.version.major = major; + range.right.version.minor = minor +| 1; + break :done; + } + range.right.version.major = major +| 1; + } + return range; + }, + .none => unreachable, + .version => { + if (this.wildcard != Wildcard.none) { + return Range.initWildcard(version.min(), this.wildcard); + } + + return .{ .left = .{ .op = .eql, .version = version.min() } }; + }, + else => {}, + } + + return switch (this.wildcard) { + .major => .{ + .left = .{ .op = .gte, .version = version.min() }, + .right = .{ + .op = .lte, + .version = .{ + .major = std.math.maxInt(u32), + .minor = std.math.maxInt(u32), + .patch = std.math.maxInt(u32), + }, + }, + }, + .minor => switch (this.tag) { + .lte => .{ + .left = .{ + .op = .lte, + .version = .{ + .major = version.major orelse 0, + .minor = std.math.maxInt(u32), + .patch = std.math.maxInt(u32), + }, + }, + }, + .lt => .{ + .left = .{ + .op = .lt, + .version = .{ + .major = version.major orelse 0, + .minor = 0, + .patch = 0, + }, + }, + }, + + .gt => .{ + .left = .{ + .op = .gt, + .version = .{ + .major = version.major orelse 0, + .minor = std.math.maxInt(u32), + .patch = std.math.maxInt(u32), + }, + }, + }, + + .gte => .{ + .left = .{ + .op = .gte, + .version = .{ + .major = version.major orelse 0, + .minor = 0, + .patch = 0, + }, + }, + }, + else => unreachable, + }, + .patch => switch (this.tag) { + .lte => .{ + .left = .{ + .op = .lte, + .version = .{ + .major = version.major orelse 0, + .minor = version.minor orelse 0, + .patch = std.math.maxInt(u32), + }, + }, + }, + .lt => .{ + .left = .{ + .op = .lt, + .version = .{ + .major = version.major orelse 0, + .minor = version.minor orelse 0, + .patch = 0, + }, + }, + }, + + .gt => .{ + .left = .{ + .op = .gt, + .version = .{ + .major = version.major orelse 0, + .minor = version.minor orelse 0, + .patch = std.math.maxInt(u32), + }, + }, + }, + + .gte => .{ + .left = .{ + .op = .gte, + .version = .{ + .major = version.major orelse 0, + .minor = version.minor orelse 0, + .patch = 0, + }, + }, + }, + else => unreachable, + }, + .none => .{ + .left = .{ + .op = switch (this.tag) { + .gt => .gt, + .gte => .gte, + .lt => .lt, + .lte => .lte, + else => unreachable, + }, + .version = version.min(), + }, + }, + }; + } + + pub const Tag = enum { + none, + gt, + gte, + lt, + lte, + version, + tilda, + caret, + }; + + pub const Wildcard = enum { + none, + major, + minor, + patch, + }; +}; + +pub fn parse( + allocator: Allocator, + input: string, + sliced: SlicedString, +) bun.OOM!Group { + var i: usize = 0; + var list = Group{ + .allocator = allocator, + .input = input, + }; + + var token = Token{}; + var prev_token = Token{}; + + var count: u8 = 0; + var skip_round = false; + var is_or = false; + + while (i < input.len) { + skip_round = false; + + switch (input[i]) { + '>' => { + if (input.len > i + 1 and input[i + 1] == '=') { + token.tag = .gte; + i += 1; + } else { + token.tag = .gt; + } + + i += 1; + while (i < input.len and input[i] == ' ') : (i += 1) {} + }, + '<' => { + if (input.len > i + 1 and input[i + 1] == '=') { + token.tag = .lte; + i += 1; + } else { + token.tag = .lt; + } + + i += 1; + while (i < input.len and input[i] == ' ') : (i += 1) {} + }, + '=', 'v' => { + token.tag = .version; + is_or = true; + i += 1; + while (i < input.len and input[i] == ' ') : (i += 1) {} + }, + '~' => { + token.tag = .tilda; + i += 1; + + if (i < input.len and input[i] == '>') i += 1; + + while (i < input.len and input[i] == ' ') : (i += 1) {} + }, + '^' => { + token.tag = .caret; + i += 1; + while (i < input.len and input[i] == ' ') : (i += 1) {} + }, + '0'...'9', 'X', 'x', '*' => { + token.tag = .version; + is_or = true; + }, + '|' => { + i += 1; + + while (i < input.len and input[i] == '|') : (i += 1) {} + while (i < input.len and input[i] == ' ') : (i += 1) {} + is_or = true; + token.tag = Token.Tag.none; + skip_round = true; + }, + '-' => { + i += 1; + while (i < input.len and input[i] == ' ') : (i += 1) {} + }, + ' ' => { + i += 1; + while (i < input.len and input[i] == ' ') : (i += 1) {} + skip_round = true; + }, + else => { + i += 1; + token.tag = Token.Tag.none; + + // skip tagged versions + // we are assuming this is the beginning of a tagged version like "boop" + // "1.0.0 || boop" + while (i < input.len and input[i] != ' ' and input[i] != '|') : (i += 1) {} + skip_round = true; + }, + } + + if (!skip_round) { + const parse_result = Version.parse(sliced.sub(input[i..])); + const version = parse_result.version.min(); + if (version.tag.hasBuild()) list.flags.setValue(Group.Flags.build, true); + if (version.tag.hasPre()) list.flags.setValue(Group.Flags.pre, true); + + token.wildcard = parse_result.wildcard; + + i += parse_result.len; + const rollback = i; + + const maybe_hyphenate = i < input.len and (input[i] == ' ' or input[i] == '-'); + + // TODO: can we do this without rolling back? + const hyphenate: bool = maybe_hyphenate and possibly_hyphenate: { + i += strings.lengthOfLeadingWhitespaceASCII(input[i..]); + if (!(i < input.len and input[i] == '-')) break :possibly_hyphenate false; + i += 1; + i += strings.lengthOfLeadingWhitespaceASCII(input[i..]); + if (i == input.len) break :possibly_hyphenate false; + if (input[i] == 'v' or input[i] == '=') { + i += 1; + } + if (i == input.len) break :possibly_hyphenate false; + i += strings.lengthOfLeadingWhitespaceASCII(input[i..]); + if (i == input.len) break :possibly_hyphenate false; + + if (!(i < input.len and switch (input[i]) { + '0'...'9', 'X', 'x', '*' => true, + else => false, + })) break :possibly_hyphenate false; + + break :possibly_hyphenate true; + }; + + if (!hyphenate) i = rollback; + i += @as(usize, @intFromBool(!hyphenate)); + + if (hyphenate) { + const second_parsed = Version.parse(sliced.sub(input[i..])); + var second_version = second_parsed.version.min(); + if (second_version.tag.hasBuild()) list.flags.setValue(Group.Flags.build, true); + if (second_version.tag.hasPre()) list.flags.setValue(Group.Flags.pre, true); + const range: Range = brk: { + switch (second_parsed.wildcard) { + .major => { + // "1.0.0 - x" --> ">=1.0.0" + break :brk Range{ + .left = .{ .op = .gte, .version = version }, + }; + }, + .minor => { + // "1.0.0 - 1.x" --> ">=1.0.0 < 2.0.0" + second_version.major +|= 1; + second_version.minor = 0; + second_version.patch = 0; + + break :brk Range{ + .left = .{ .op = .gte, .version = version }, + .right = .{ .op = .lt, .version = second_version }, + }; + }, + .patch => { + // "1.0.0 - 1.0.x" --> ">=1.0.0 <1.1.0" + second_version.minor +|= 1; + second_version.patch = 0; + + break :brk Range{ + .left = .{ .op = .gte, .version = version }, + .right = .{ .op = .lt, .version = second_version }, + }; + }, + .none => { + break :brk Range{ + .left = .{ .op = .gte, .version = version }, + .right = .{ .op = .lte, .version = second_version }, + }; + }, + } + }; + + if (is_or) { + try list.orRange(range); + } else { + try list.andRange(range); + } + + i += second_parsed.len + 1; + } else if (count == 0 and token.tag == .version) { + switch (parse_result.wildcard) { + .none => { + try list.orVersion(version); + }, + else => { + try list.orRange(token.toRange(parse_result.version)); + }, + } + } else if (count == 0) { + // From a semver perspective, treat "--foo" the same as "-foo" + // example: foo/bar@1.2.3@--canary.24 + // ^ + if (token.tag == .none) { + is_or = false; + token.wildcard = .none; + prev_token.tag = .none; + continue; + } + try list.andRange(token.toRange(parse_result.version)); + } else if (is_or) { + try list.orRange(token.toRange(parse_result.version)); + } else { + try list.andRange(token.toRange(parse_result.version)); + } + + is_or = false; + count += 1; + token.wildcard = .none; + prev_token.tag = token.tag; + } + } + + return list; +} + +const Query = @This(); + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = @import("../identity_context.zig").IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const ExternalString = bun.Semver.ExternalString; +const SlicedString = bun.Semver.SlicedString; +const String = bun.Semver.String; +const Version = bun.Semver.Version; +const Range = bun.Semver.Range; +const assert = bun.assert; diff --git a/src/semver/SemverRange.zig b/src/semver/SemverRange.zig new file mode 100644 index 00000000000000..ccc0f4ec5056d1 --- /dev/null +++ b/src/semver/SemverRange.zig @@ -0,0 +1,273 @@ +pub const Op = enum(u8) { + unset = 0, + eql = 1, + lt = 3, + lte = 4, + gt = 5, + gte = 6, +}; + +left: Comparator = .{}, +right: Comparator = .{}, + +pub fn format(this: Range, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + if (this.left.op == .unset and this.right.op == .unset) { + return; + } + + if (this.right.op == .unset) { + try std.fmt.format(writer, "{}", .{this.left}); + } else { + try std.fmt.format(writer, "{} {}", .{ this.left, this.right }); + } +} + +/// * +/// >= 0.0.0 +/// >= 0 +/// >= 0.0 +/// >= x +/// >= 0 +pub fn anyRangeSatisfies(this: *const Range) bool { + return this.left.op == .gte and this.left.version.eql(.{}); +} + +pub fn initWildcard(version: Version, wildcard: Query.Token.Wildcard) Range { + switch (wildcard) { + .none => { + return .{ + .left = .{ + .op = Op.eql, + .version = version, + }, + }; + }, + + .major => { + return .{ + .left = .{ + .op = Op.gte, + .version = .{ + // .raw = version.raw + }, + }, + }; + }, + .minor => { + const lhs = Version{ + .major = version.major +| 1, + // .raw = version.raw + }; + const rhs = Version{ + .major = version.major, + // .raw = version.raw + }; + return .{ + .left = .{ + .op = Op.lt, + .version = lhs, + }, + .right = .{ + .op = Op.gte, + .version = rhs, + }, + }; + }, + .patch => { + const lhs = Version{ + .major = version.major, + .minor = version.minor +| 1, + // .raw = version.raw; + }; + const rhs = Version{ + .major = version.major, + .minor = version.minor, + // .raw = version.raw; + }; + return Range{ + .left = .{ + .op = Op.lt, + .version = lhs, + }, + .right = .{ + .op = Op.gte, + .version = rhs, + }, + }; + }, + } +} + +pub inline fn hasLeft(this: Range) bool { + return this.left.op != Op.unset; +} + +pub inline fn hasRight(this: Range) bool { + return this.right.op != Op.unset; +} + +/// Is the Range equal to another Range +/// This does not evaluate the range. +pub inline fn eql(lhs: Range, rhs: Range) bool { + return lhs.left.eql(rhs.left) and lhs.right.eql(rhs.right); +} + +pub const Formatter = struct { + buffer: []const u8, + range: *const Range, + + pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + if (this.range.left.op == Op.unset and this.range.right.op == Op.unset) { + return; + } + + if (this.range.right.op == .unset) { + try std.fmt.format(writer, "{}", .{this.range.left.fmt(this.buffer)}); + } else { + try std.fmt.format(writer, "{} {}", .{ this.range.left.fmt(this.buffer), this.range.right.fmt(this.buffer) }); + } + } +}; + +pub fn fmt(this: *const Range, buf: []const u8) @This().Formatter { + return .{ .buffer = buf, .range = this }; +} + +pub const Comparator = struct { + op: Op = .unset, + version: Version = .{}, + + pub inline fn eql(lhs: Comparator, rhs: Comparator) bool { + return lhs.op == rhs.op and lhs.version.eql(rhs.version); + } + + pub const Formatter = struct { + buffer: []const u8, + comparator: *const Comparator, + + pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + if (this.comparator.op == Op.unset) { + return; + } + + switch (this.comparator.op) { + .unset => unreachable, // see above, + .eql => try writer.writeAll("=="), + .lt => try writer.writeAll("<"), + .lte => try writer.writeAll("<="), + .gt => try writer.writeAll(">"), + .gte => try writer.writeAll(">="), + } + + try std.fmt.format(writer, "{}", .{this.comparator.version.fmt(this.buffer)}); + } + }; + + pub fn fmt(this: *const Comparator, buf: []const u8) @This().Formatter { + return .{ .buffer = buf, .comparator = this }; + } + + pub fn satisfies( + comparator: Comparator, + version: Version, + comparator_buf: string, + version_buf: string, + ) bool { + const order = version.orderWithoutBuild(comparator.version, version_buf, comparator_buf); + + return switch (order) { + .eq => switch (comparator.op) { + .lte, .gte, .eql => true, + else => false, + }, + .gt => switch (comparator.op) { + .gt, .gte => true, + else => false, + }, + .lt => switch (comparator.op) { + .lt, .lte => true, + else => false, + }, + }; + } +}; + +pub fn satisfies(range: Range, version: Version, range_buf: string, version_buf: string) bool { + const has_left = range.hasLeft(); + const has_right = range.hasRight(); + + if (!has_left) { + return true; + } + + if (!range.left.satisfies(version, range_buf, version_buf)) { + return false; + } + + if (has_right and !range.right.satisfies(version, range_buf, version_buf)) { + return false; + } + + return true; +} + +pub fn satisfiesPre(range: Range, version: Version, range_buf: string, version_buf: string, pre_matched: *bool) bool { + if (comptime Environment.allow_assert) { + assert(version.tag.hasPre()); + } + const has_left = range.hasLeft(); + const has_right = range.hasRight(); + + if (!has_left) { + return true; + } + + // If left has prerelease check if major,minor,patch matches with left. If + // not, check the same with right if right exists and has prerelease. + pre_matched.* = pre_matched.* or + (range.left.version.tag.hasPre() and + version.patch == range.left.version.patch and + version.minor == range.left.version.minor and + version.major == range.left.version.major) or + (has_right and + range.right.version.tag.hasPre() and + version.patch == range.right.version.patch and + version.minor == range.right.version.minor and + version.major == range.right.version.major); + + if (!range.left.satisfies(version, range_buf, version_buf)) { + return false; + } + + if (has_right and !range.right.satisfies(version, range_buf, version_buf)) { + return false; + } + + return true; +} + +const Range = @This(); + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = @import("../identity_context.zig").IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const ExternalString = bun.Semver.ExternalString; +const SlicedString = bun.Semver.SlicedString; +const String = bun.Semver.String; +const Version = bun.Semver.Version; +const Query = bun.Semver.Query; +const assert = bun.assert; diff --git a/src/semver/SemverString.zig b/src/semver/SemverString.zig new file mode 100644 index 00000000000000..04d3f75dc80212 --- /dev/null +++ b/src/semver/SemverString.zig @@ -0,0 +1,628 @@ +/// String type that stores either an offset/length into an external buffer or a string inline directly +pub const String = extern struct { + pub const max_inline_len: usize = 8; + /// This is three different types of string. + /// 1. Empty string. If it's all zeroes, then it's an empty string. + /// 2. If the final bit is set, then it's a string that is stored inline. + /// 3. If the final bit is not set, then it's a string that is stored in an external buffer. + bytes: [max_inline_len]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }, + + /// Create an inline string + pub fn from(comptime inlinable_buffer: []const u8) String { + comptime { + if (inlinable_buffer.len > max_inline_len or + inlinable_buffer.len == max_inline_len and + inlinable_buffer[max_inline_len - 1] >= 0x80) + { + @compileError("string constant too long to be inlined"); + } + } + return String.init(inlinable_buffer, inlinable_buffer); + } + + pub const Buf = struct { + bytes: *std.ArrayListUnmanaged(u8), + allocator: std.mem.Allocator, + pool: *Builder.StringPool, + + pub fn init(lockfile: *const Lockfile) Buf { + return .{ + .bytes = &lockfile.buffers.string_bytes, + .allocator = lockfile.allocator, + .pool = &lockfile.string_pool, + }; + } + + pub fn append(this: *Buf, str: string) OOM!String { + if (canInline(str)) { + return String.initInline(str); + } + + const hash = Builder.stringHash(str); + const entry = try this.pool.getOrPut(hash); + if (entry.found_existing) { + return entry.value_ptr.*; + } + + // new entry + const new = try String.initAppend(this.allocator, this.bytes, str); + entry.value_ptr.* = new; + return new; + } + + pub fn appendWithHash(this: *Buf, str: string, hash: u64) OOM!String { + if (canInline(str)) { + return initInline(str); + } + + const entry = try this.pool.getOrPut(hash); + if (entry.found_existing) { + return entry.value_ptr.*; + } + + // new entry + const new = try String.initAppend(this.allocator, this.bytes, str); + entry.value_ptr.* = new; + return new; + } + + pub fn appendExternal(this: *Buf, str: string) OOM!ExternalString { + const hash = Builder.stringHash(str); + + if (canInline(str)) { + return .{ + .value = String.initInline(str), + .hash = hash, + }; + } + + const entry = try this.pool.getOrPut(hash); + if (entry.found_existing) { + return .{ + .value = entry.value_ptr.*, + .hash = hash, + }; + } + + const new = try String.initAppend(this.allocator, this.bytes, str); + entry.value_ptr.* = new; + return .{ + .value = new, + .hash = hash, + }; + } + + pub fn appendExternalWithHash(this: *Buf, str: string, hash: u64) OOM!ExternalString { + if (canInline(str)) { + return .{ + .value = initInline(str), + .hash = hash, + }; + } + + const entry = try this.pool.getOrPut(hash); + if (entry.found_existing) { + return .{ + .value = entry.value_ptr.*, + .hash = hash, + }; + } + + const new = try String.initAppend(this.allocator, this.bytes, str); + entry.value_ptr.* = new; + return .{ + .value = new, + .hash = hash, + }; + } + }; + + pub const Tag = enum { + small, + big, + }; + + pub inline fn fmt(self: *const String, buf: []const u8) Formatter { + return Formatter{ + .buf = buf, + .str = self, + }; + } + + pub const Formatter = struct { + str: *const String, + buf: string, + + pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const str = formatter.str; + try writer.writeAll(str.slice(formatter.buf)); + } + }; + + /// Escapes for json. Defaults to quoting the string. + pub inline fn fmtJson(self: *const String, buf: []const u8, opts: JsonFormatter.Options) JsonFormatter { + return .{ + .buf = buf, + .str = self, + .opts = opts, + }; + } + + pub const JsonFormatter = struct { + str: *const String, + buf: string, + opts: Options, + + pub const Options = struct { + quote: bool = true, + }; + + pub fn format(formatter: JsonFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + try writer.print("{}", .{bun.fmt.formatJSONStringUTF8(formatter.str.slice(formatter.buf), .{ .quote = formatter.opts.quote })}); + } + }; + + pub fn Sorter(comptime direction: enum { asc, desc }) type { + return struct { + lhs_buf: []const u8, + rhs_buf: []const u8, + pub fn lessThan(this: @This(), lhs: String, rhs: String) bool { + return lhs.order(&rhs, this.lhs_buf, this.rhs_buf) == if (comptime direction == .asc) .lt else .gt; + } + }; + } + + pub inline fn order( + lhs: *const String, + rhs: *const String, + lhs_buf: []const u8, + rhs_buf: []const u8, + ) std.math.Order { + return strings.order(lhs.slice(lhs_buf), rhs.slice(rhs_buf)); + } + + pub inline fn canInline(buf: []const u8) bool { + return switch (buf.len) { + 0...max_inline_len - 1 => true, + max_inline_len => buf[max_inline_len - 1] & 0x80 == 0, + else => false, + }; + } + + pub inline fn isInline(this: String) bool { + return this.bytes[max_inline_len - 1] & 0x80 == 0; + } + + pub inline fn sliced(this: *const String, buf: []const u8) SlicedString { + return if (this.isInline()) + SlicedString.init(this.slice(""), this.slice("")) + else + SlicedString.init(buf, this.slice(buf)); + } + + // https://en.wikipedia.org/wiki/Intel_5-level_paging + // https://developer.arm.com/documentation/101811/0101/Address-spaces-in-AArch64#:~:text=0%2DA%2C%20the%20maximum%20size,2%2DA. + // X64 seems to need some of the pointer bits + const max_addressable_space = u63; + + comptime { + if (@sizeOf(usize) != 8) { + @compileError("This code needs to be updated for non-64-bit architectures"); + } + } + + pub const HashContext = struct { + a_buf: []const u8, + b_buf: []const u8, + + pub fn eql(ctx: HashContext, a: String, b: String) bool { + return a.eql(b, ctx.a_buf, ctx.b_buf); + } + + pub fn hash(ctx: HashContext, a: String) u64 { + const str = a.slice(ctx.a_buf); + return bun.hash(str); + } + }; + + pub const ArrayHashContext = struct { + a_buf: []const u8, + b_buf: []const u8, + + pub fn eql(ctx: ArrayHashContext, a: String, b: String, _: usize) bool { + return a.eql(b, ctx.a_buf, ctx.b_buf); + } + + pub fn hash(ctx: ArrayHashContext, a: String) u32 { + const str = a.slice(ctx.a_buf); + return @as(u32, @truncate(bun.hash(str))); + } + }; + + pub fn init( + buf: string, + in: string, + ) String { + return switch (in.len) { + 0 => String{}, + 1 => String{ .bytes = .{ in[0], 0, 0, 0, 0, 0, 0, 0 } }, + 2 => String{ .bytes = .{ in[0], in[1], 0, 0, 0, 0, 0, 0 } }, + 3 => String{ .bytes = .{ in[0], in[1], in[2], 0, 0, 0, 0, 0 } }, + 4 => String{ .bytes = .{ in[0], in[1], in[2], in[3], 0, 0, 0, 0 } }, + 5 => String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], 0, 0, 0 } }, + 6 => String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], 0, 0 } }, + 7 => String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], 0 } }, + max_inline_len => + // If they use the final bit, then it's a big string. + // This should only happen for non-ascii strings that are exactly 8 bytes. + // so that's an edge-case + if ((in[max_inline_len - 1]) >= 128) + @as(String, @bitCast((@as( + u64, + 0, + ) | @as( + u64, + @as( + max_addressable_space, + @truncate(@as( + u64, + @bitCast(Pointer.init(buf, in)), + )), + ), + )) | 1 << 63)) + else + String{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] } }, + + else => @as( + String, + @bitCast((@as( + u64, + 0, + ) | @as( + u64, + @as( + max_addressable_space, + @truncate(@as( + u64, + @bitCast(Pointer.init(buf, in)), + )), + ), + )) | 1 << 63), + ), + }; + } + + pub fn initInline( + in: string, + ) String { + bun.assertWithLocation(canInline(in), @src()); + return switch (in.len) { + 0 => .{}, + 1 => .{ .bytes = .{ in[0], 0, 0, 0, 0, 0, 0, 0 } }, + 2 => .{ .bytes = .{ in[0], in[1], 0, 0, 0, 0, 0, 0 } }, + 3 => .{ .bytes = .{ in[0], in[1], in[2], 0, 0, 0, 0, 0 } }, + 4 => .{ .bytes = .{ in[0], in[1], in[2], in[3], 0, 0, 0, 0 } }, + 5 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], 0, 0, 0 } }, + 6 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], 0, 0 } }, + 7 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], 0 } }, + 8 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] } }, + else => unreachable, + }; + } + + pub fn initAppendIfNeeded( + allocator: std.mem.Allocator, + buf: *std.ArrayListUnmanaged(u8), + in: string, + ) OOM!String { + return switch (in.len) { + 0 => .{}, + 1 => .{ .bytes = .{ in[0], 0, 0, 0, 0, 0, 0, 0 } }, + 2 => .{ .bytes = .{ in[0], in[1], 0, 0, 0, 0, 0, 0 } }, + 3 => .{ .bytes = .{ in[0], in[1], in[2], 0, 0, 0, 0, 0 } }, + 4 => .{ .bytes = .{ in[0], in[1], in[2], in[3], 0, 0, 0, 0 } }, + 5 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], 0, 0, 0 } }, + 6 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], 0, 0 } }, + 7 => .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], 0 } }, + + max_inline_len => + // If they use the final bit, then it's a big string. + // This should only happen for non-ascii strings that are exactly 8 bytes. + // so that's an edge-case + if ((in[max_inline_len - 1]) >= 128) + try initAppend(allocator, buf, in) + else + .{ .bytes = .{ in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] } }, + + else => try initAppend(allocator, buf, in), + }; + } + + pub fn initAppend( + allocator: std.mem.Allocator, + buf: *std.ArrayListUnmanaged(u8), + in: string, + ) OOM!String { + try buf.appendSlice(allocator, in); + const in_buf = buf.items[buf.items.len - in.len ..]; + return @bitCast((@as(u64, 0) | @as(u64, @as(max_addressable_space, @truncate(@as(u64, @bitCast(Pointer.init(buf.items, in_buf))))))) | 1 << 63); + } + + pub fn eql(this: String, that: String, this_buf: []const u8, that_buf: []const u8) bool { + if (this.isInline() and that.isInline()) { + return @as(u64, @bitCast(this.bytes)) == @as(u64, @bitCast(that.bytes)); + } else if (this.isInline() != that.isInline()) { + return false; + } else { + const a = this.ptr(); + const b = that.ptr(); + return strings.eql(this_buf[a.off..][0..a.len], that_buf[b.off..][0..b.len]); + } + } + + pub inline fn isEmpty(this: String) bool { + return @as(u64, @bitCast(this.bytes)) == @as(u64, 0); + } + + pub fn len(this: String) usize { + switch (this.bytes[max_inline_len - 1] & 128) { + 0 => { + // Edgecase: string that starts with a 0 byte will be considered empty. + switch (this.bytes[0]) { + 0 => { + return 0; + }, + else => { + comptime var i: usize = 0; + + inline while (i < this.bytes.len) : (i += 1) { + if (this.bytes[i] == 0) return i; + } + + return 8; + }, + } + }, + else => { + const ptr_ = this.ptr(); + return ptr_.len; + }, + } + } + + pub const Pointer = extern struct { + off: u32 = 0, + len: u32 = 0, + + pub inline fn init( + buf: string, + in: string, + ) Pointer { + if (Environment.allow_assert) { + assert(bun.isSliceInBuffer(in, buf)); + } + + return Pointer{ + .off = @as(u32, @truncate(@intFromPtr(in.ptr) - @intFromPtr(buf.ptr))), + .len = @as(u32, @truncate(in.len)), + }; + } + }; + + pub inline fn ptr(this: String) Pointer { + return @as(Pointer, @bitCast(@as(u64, @as(u63, @truncate(@as(u64, @bitCast(this))))))); + } + + pub fn toJS(this: *const String, buffer: []const u8, globalThis: *JSC.JSGlobalObject) JSC.JSValue { + return bun.String.createUTF8ForJS(globalThis, this.slice(buffer)); + } + + // String must be a pointer because we reference it as a slice. It will become a dead pointer if it is copied. + pub fn slice(this: *const String, buf: string) string { + switch (this.bytes[max_inline_len - 1] & 128) { + 0 => { + // Edgecase: string that starts with a 0 byte will be considered empty. + switch (this.bytes[0]) { + 0 => { + return ""; + }, + else => { + comptime var i: usize = 0; + + inline while (i < this.bytes.len) : (i += 1) { + if (this.bytes[i] == 0) return this.bytes[0..i]; + } + + return &this.bytes; + }, + } + }, + else => { + const ptr_ = this.*.ptr(); + return buf[ptr_.off..][0..ptr_.len]; + }, + } + } + + pub const Builder = struct { + len: usize = 0, + cap: usize = 0, + ptr: ?[*]u8 = null, + string_pool: StringPool = undefined, + + pub const StringPool = std.HashMap(u64, String, IdentityContext(u64), 80); + + pub inline fn stringHash(buf: []const u8) u64 { + return bun.Wyhash11.hash(0, buf); + } + + pub inline fn count(this: *Builder, slice_: string) void { + return countWithHash(this, slice_, if (slice_.len >= String.max_inline_len) stringHash(slice_) else std.math.maxInt(u64)); + } + + pub inline fn countWithHash(this: *Builder, slice_: string, hash: u64) void { + if (slice_.len <= String.max_inline_len) return; + + if (!this.string_pool.contains(hash)) { + this.cap += slice_.len; + } + } + + pub inline fn allocatedSlice(this: *Builder) []u8 { + return if (this.cap > 0) + this.ptr.?[0..this.cap] + else + &[_]u8{}; + } + pub fn allocate(this: *Builder, allocator: Allocator) !void { + const ptr_ = try allocator.alloc(u8, this.cap); + this.ptr = ptr_.ptr; + } + + pub fn append(this: *Builder, comptime Type: type, slice_: string) Type { + return @call(bun.callmod_inline, appendWithHash, .{ this, Type, slice_, stringHash(slice_) }); + } + + pub fn appendUTF8WithoutPool(this: *Builder, comptime Type: type, slice_: string, hash: u64) Type { + if (slice_.len <= String.max_inline_len) { + if (strings.isAllASCII(slice_)) { + switch (Type) { + String => { + return String.init(this.allocatedSlice(), slice_); + }, + ExternalString => { + return ExternalString.init(this.allocatedSlice(), slice_, hash); + }, + else => @compileError("Invalid type passed to StringBuilder"), + } + } + } + + if (comptime Environment.allow_assert) { + assert(this.len <= this.cap); // didn't count everything + assert(this.ptr != null); // must call allocate first + } + + bun.copy(u8, this.ptr.?[this.len..this.cap], slice_); + const final_slice = this.ptr.?[this.len..this.cap][0..slice_.len]; + this.len += slice_.len; + + if (comptime Environment.allow_assert) assert(this.len <= this.cap); + + switch (Type) { + String => { + return String.init(this.allocatedSlice(), final_slice); + }, + ExternalString => { + return ExternalString.init(this.allocatedSlice(), final_slice, hash); + }, + else => @compileError("Invalid type passed to StringBuilder"), + } + } + + // SlicedString is not supported due to inline strings. + pub fn appendWithoutPool(this: *Builder, comptime Type: type, slice_: string, hash: u64) Type { + if (slice_.len <= String.max_inline_len) { + switch (Type) { + String => { + return String.init(this.allocatedSlice(), slice_); + }, + ExternalString => { + return ExternalString.init(this.allocatedSlice(), slice_, hash); + }, + else => @compileError("Invalid type passed to StringBuilder"), + } + } + if (comptime Environment.allow_assert) { + assert(this.len <= this.cap); // didn't count everything + assert(this.ptr != null); // must call allocate first + } + + bun.copy(u8, this.ptr.?[this.len..this.cap], slice_); + const final_slice = this.ptr.?[this.len..this.cap][0..slice_.len]; + this.len += slice_.len; + + if (comptime Environment.allow_assert) assert(this.len <= this.cap); + + switch (Type) { + String => { + return String.init(this.allocatedSlice(), final_slice); + }, + ExternalString => { + return ExternalString.init(this.allocatedSlice(), final_slice, hash); + }, + else => @compileError("Invalid type passed to StringBuilder"), + } + } + + pub fn appendWithHash(this: *Builder, comptime Type: type, slice_: string, hash: u64) Type { + if (slice_.len <= String.max_inline_len) { + switch (Type) { + String => { + return String.init(this.allocatedSlice(), slice_); + }, + ExternalString => { + return ExternalString.init(this.allocatedSlice(), slice_, hash); + }, + else => @compileError("Invalid type passed to StringBuilder"), + } + } + + if (comptime Environment.allow_assert) { + assert(this.len <= this.cap); // didn't count everything + assert(this.ptr != null); // must call allocate first + } + + const string_entry = this.string_pool.getOrPut(hash) catch unreachable; + if (!string_entry.found_existing) { + bun.copy(u8, this.ptr.?[this.len..this.cap], slice_); + const final_slice = this.ptr.?[this.len..this.cap][0..slice_.len]; + this.len += slice_.len; + + string_entry.value_ptr.* = String.init(this.allocatedSlice(), final_slice); + } + + if (comptime Environment.allow_assert) assert(this.len <= this.cap); + + switch (Type) { + String => { + return string_entry.value_ptr.*; + }, + ExternalString => { + return ExternalString{ + .value = string_entry.value_ptr.*, + .hash = hash, + }; + }, + else => @compileError("Invalid type passed to StringBuilder"), + } + } + }; + + comptime { + if (@sizeOf(String) != @sizeOf(Pointer)) { + @compileError("String types must be the same size"); + } + } +}; + +const assert = bun.assert; +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = bun.IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const ExternalString = bun.Semver.ExternalString; +const SlicedString = bun.Semver.SlicedString; diff --git a/src/semver/SlicedString.zig b/src/semver/SlicedString.zig new file mode 100644 index 00000000000000..960c20a8b85b97 --- /dev/null +++ b/src/semver/SlicedString.zig @@ -0,0 +1,58 @@ +buf: string, +slice: string, + +pub inline fn init(buf: string, slice: string) SlicedString { + if (Environment.allow_assert and !@inComptime()) { + if (@intFromPtr(buf.ptr) > @intFromPtr(slice.ptr)) { + @panic("SlicedString.init buf is not in front of slice"); + } + } + return SlicedString{ .buf = buf, .slice = slice }; +} + +pub inline fn external(this: SlicedString) ExternalString { + if (comptime Environment.allow_assert) { + assert(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.slice.ptr) and ((@intFromPtr(this.slice.ptr) + this.slice.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len))); + } + + return ExternalString.init(this.buf, this.slice, bun.Wyhash11.hash(0, this.slice)); +} + +pub inline fn value(this: SlicedString) String { + if (comptime Environment.allow_assert) { + assert(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.slice.ptr) and ((@intFromPtr(this.slice.ptr) + this.slice.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len))); + } + + return String.init(this.buf, this.slice); +} + +pub inline fn sub(this: SlicedString, input: string) SlicedString { + if (Environment.allow_assert) { + if (!(@intFromPtr(this.buf.ptr) <= @intFromPtr(this.buf.ptr) and ((@intFromPtr(input.ptr) + input.len) <= (@intFromPtr(this.buf.ptr) + this.buf.len)))) { + @panic("SlicedString.sub input is not a substring of the slice"); + } + } + return SlicedString{ .buf = this.buf, .slice = input }; +} + +const SlicedString = @This(); +const assert = bun.assert; +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = bun.IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const ExternalString = bun.Semver.ExternalString; +const String = bun.Semver.String; diff --git a/src/semver/Version.zig b/src/semver/Version.zig new file mode 100644 index 00000000000000..2073f981484369 --- /dev/null +++ b/src/semver/Version.zig @@ -0,0 +1,1010 @@ +pub const Version = extern struct { + major: u32 = 0, + minor: u32 = 0, + patch: u32 = 0, + _tag_padding: [4]u8 = .{0} ** 4, // [see padding_checker.zig] + tag: Tag = .{}, + + /// Assumes that there is only one buffer for all the strings + pub fn sortGt(ctx: []const u8, lhs: Version, rhs: Version) bool { + return orderFn(ctx, lhs, rhs) == .gt; + } + + pub fn orderFn(ctx: []const u8, lhs: Version, rhs: Version) std.math.Order { + return lhs.order(rhs, ctx, ctx); + } + + pub fn isZero(this: Version) bool { + return this.patch == 0 and this.minor == 0 and this.major == 0; + } + + pub fn parseUTF8(slice: []const u8) ParseResult { + return parse(.{ .buf = slice, .slice = slice }); + } + + pub fn cloneInto(this: Version, slice: []const u8, buf: *[]u8) Version { + return .{ + .major = this.major, + .minor = this.minor, + .patch = this.patch, + .tag = this.tag.cloneInto(slice, buf), + }; + } + + pub inline fn len(this: *const Version) u32 { + return this.tag.build.len + this.tag.pre.len; + } + + pub const Formatter = struct { + version: Version, + input: string, + + pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { + const self = formatter.version; + try std.fmt.format(writer, "{?d}.{?d}.{?d}", .{ self.major, self.minor, self.patch }); + + if (self.tag.hasPre()) { + const pre = self.tag.pre.slice(formatter.input); + try writer.writeAll("-"); + try writer.writeAll(pre); + } + + if (self.tag.hasBuild()) { + const build = self.tag.build.slice(formatter.input); + try writer.writeAll("+"); + try writer.writeAll(build); + } + } + }; + + pub fn fmt(this: Version, input: string) Formatter { + return .{ .version = this, .input = input }; + } + + pub const DiffFormatter = struct { + version: Version, + buf: string, + other: Version, + other_buf: string, + + pub fn format(this: DiffFormatter, comptime fmt_: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { + if (!Output.enable_ansi_colors) { + // print normally if no colors + const formatter: Formatter = .{ .version = this.version, .input = this.buf }; + return Formatter.format(formatter, fmt_, options, writer); + } + + const diff = this.version.whichVersionIsDifferent(this.other, this.buf, this.other_buf) orelse .none; + + switch (diff) { + .major => try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ + this.version.major, this.version.minor, this.version.patch, + }), + .minor => { + if (this.version.major == 0) { + try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ + this.version.major, this.version.minor, this.version.patch, + }); + } else { + try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ + this.version.major, this.version.minor, this.version.patch, + }); + } + }, + .patch => { + if (this.version.major == 0 and this.version.minor == 0) { + try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ + this.version.major, this.version.minor, this.version.patch, + }); + } else { + try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ + this.version.major, this.version.minor, this.version.patch, + }); + } + }, + .none, .pre, .build => try writer.print(Output.prettyFmt("{d}.{d}.{d}", true), .{ + this.version.major, this.version.minor, this.version.patch, + }), + } + + // might be pre or build. loop through all characters, and insert on + // first diff. + + var set_color = false; + if (this.version.tag.hasPre()) { + if (this.other.tag.hasPre()) { + const pre = this.version.tag.pre.slice(this.buf); + const other_pre = this.other.tag.pre.slice(this.other_buf); + + var first = true; + for (pre, 0..) |c, i| { + if (!set_color and i < other_pre.len and c != other_pre[i]) { + set_color = true; + try writer.writeAll(Output.prettyFmt("", true)); + } + if (first) { + first = false; + try writer.writeByte('-'); + } + try writer.writeByte(c); + } + } else { + try writer.print(Output.prettyFmt("-{}", true), .{this.version.tag.pre.fmt(this.buf)}); + set_color = true; + } + } + + if (this.version.tag.hasBuild()) { + if (this.other.tag.hasBuild()) { + const build = this.version.tag.build.slice(this.buf); + const other_build = this.other.tag.build.slice(this.other_buf); + + var first = true; + for (build, 0..) |c, i| { + if (!set_color and i < other_build.len and c != other_build[i]) { + set_color = true; + try writer.writeAll(Output.prettyFmt("", true)); + } + if (first) { + first = false; + try writer.writeByte('+'); + } + try writer.writeByte(c); + } + } else { + if (!set_color) { + try writer.print(Output.prettyFmt("+{}", true), .{this.version.tag.build.fmt(this.buf)}); + } else { + try writer.print("+{}", .{this.version.tag.build.fmt(this.other_buf)}); + } + } + } + + try writer.writeAll(Output.prettyFmt("", true)); + } + }; + + pub fn diffFmt(this: Version, other: Version, this_buf: string, other_buf: string) DiffFormatter { + return .{ + .version = this, + .buf = this_buf, + .other = other, + .other_buf = other_buf, + }; + } + + pub const ChangedVersion = enum { + major, + minor, + patch, + pre, + build, + none, + }; + + pub fn whichVersionIsDifferent( + left: Version, + right: Version, + left_buf: string, + right_buf: string, + ) ?ChangedVersion { + if (left.major != right.major) return .major; + if (left.minor != right.minor) return .minor; + if (left.patch != right.patch) return .patch; + + if (left.tag.hasPre() != right.tag.hasPre()) return .pre; + if (!left.tag.hasPre() and !right.tag.hasPre()) return null; + if (left.tag.orderPre(right.tag, left_buf, right_buf) != .eq) return .pre; + + if (left.tag.hasBuild() != right.tag.hasBuild()) return .build; + if (!left.tag.hasBuild() and !right.tag.hasBuild()) return null; + return if (left.tag.build.order(&right.tag.build, left_buf, right_buf) != .eq) + .build + else + null; + } + + pub fn count(this: *const Version, buf: []const u8, comptime StringBuilder: type, builder: StringBuilder) void { + if (this.tag.hasPre() and !this.tag.pre.isInline()) builder.count(this.tag.pre.slice(buf)); + if (this.tag.hasBuild() and !this.tag.build.isInline()) builder.count(this.tag.build.slice(buf)); + } + + pub fn append(this: *const Version, buf: []const u8, comptime StringBuilder: type, builder: StringBuilder) Version { + var that = this.*; + + if (this.tag.hasPre() and !this.tag.pre.isInline()) that.tag.pre = builder.append(ExternalString, this.tag.pre.slice(buf)); + if (this.tag.hasBuild() and !this.tag.build.isInline()) that.tag.build = builder.append(ExternalString, this.tag.build.slice(buf)); + + return that; + } + + pub const Partial = struct { + major: ?u32 = null, + minor: ?u32 = null, + patch: ?u32 = null, + tag: Tag = .{}, + + pub fn min(this: Partial) Version { + return .{ + .major = this.major orelse 0, + .minor = this.minor orelse 0, + .patch = this.patch orelse 0, + .tag = this.tag, + }; + } + + pub fn max(this: Partial) Version { + return .{ + .major = this.major orelse std.math.maxInt(u32), + .minor = this.minor orelse std.math.maxInt(u32), + .patch = this.patch orelse std.math.maxInt(u32), + .tag = this.tag, + }; + } + }; + + const Hashable = extern struct { + major: u32, + minor: u32, + patch: u32, + pre: u64, + build: u64, + }; + + pub fn hash(this: Version) u64 { + const hashable = Hashable{ + .major = this.major, + .minor = this.minor, + .patch = this.patch, + .pre = this.tag.pre.hash, + .build = this.tag.build.hash, + }; + const bytes = std.mem.asBytes(&hashable); + return bun.Wyhash.hash(0, bytes); + } + + pub fn eql(lhs: Version, rhs: Version) bool { + return lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch and rhs.tag.eql(lhs.tag); + } + + pub const HashContext = struct { + pub fn hash(_: @This(), lhs: Version) u32 { + return @as(u32, @truncate(lhs.hash())); + } + + pub fn eql(_: @This(), lhs: Version, rhs: Version) bool { + return lhs.eql(rhs); + } + }; + + pub const PinnedVersion = enum { + major, // ^ + minor, // ~ + patch, // = + }; + + /// Modified version of pnpm's `whichVersionIsPinned` + /// https://github.com/pnpm/pnpm/blob/bc0618cf192a9cafd0ab171a3673e23ed0869bbd/packages/which-version-is-pinned/src/index.ts#L9 + /// + /// Differences: + /// - It's not used for workspaces + /// - `npm:` is assumed already removed from aliased versions + /// - Invalid input is considered major pinned (important because these strings are coming + /// from package.json) + /// + /// The goal of this function is to avoid a complete parse of semver that's unused + pub fn whichVersionIsPinned(input: string) PinnedVersion { + const version = strings.trim(input, &strings.whitespace_chars); + + var i: usize = 0; + + const pinned: PinnedVersion = pinned: { + for (0..version.len) |j| { + switch (version[j]) { + // newlines & whitespace + ' ', + '\t', + '\n', + '\r', + std.ascii.control_code.vt, + std.ascii.control_code.ff, + + // version separators + 'v', + '=', + => {}, + + else => |c| { + i = j; + + switch (c) { + '~', '^' => { + i += 1; + + for (i..version.len) |k| { + switch (version[k]) { + ' ', + '\t', + '\n', + '\r', + std.ascii.control_code.vt, + std.ascii.control_code.ff, + => { + // `v` and `=` not included. + // `~v==1` would update to `^1.1.0` if versions `1.0.0`, `1.0.1`, `1.1.0`, and `2.0.0` are available + // note that `~` changes to `^` + }, + + else => { + i = k; + break :pinned if (c == '~') .minor else .major; + }, + } + } + + // entire version after `~` is whitespace. invalid + return .major; + }, + + '0'...'9' => break :pinned .patch, + + // could be invalid, could also be valid range syntax (>=, ...) + // either way, pin major + else => return .major, + } + }, + } + } + + // entire semver is whitespace, `v`, and `=`. Invalid + return .major; + }; + + // `pinned` is `.major`, `.minor`, or `.patch`. Check for each version core number: + // - if major is missing, return `if (pinned == .patch) .major else pinned` + // - if minor is missing, return `if (pinned == .patch) .minor else pinned` + // - if patch is missing, return `pinned` + // - if there's whitespace or non-digit characters between core numbers, return `.major` + // - if the end is reached, return `pinned` + + // major + if (i >= version.len or !std.ascii.isDigit(version[i])) return .major; + var d = version[i]; + while (std.ascii.isDigit(d)) { + i += 1; + if (i >= version.len) return if (pinned == .patch) .major else pinned; + d = version[i]; + } + + if (d != '.') return .major; + + // minor + i += 1; + if (i >= version.len or !std.ascii.isDigit(version[i])) return .major; + d = version[i]; + while (std.ascii.isDigit(d)) { + i += 1; + if (i >= version.len) return if (pinned == .patch) .minor else pinned; + d = version[i]; + } + + if (d != '.') return .major; + + // patch + i += 1; + if (i >= version.len or !std.ascii.isDigit(version[i])) return .major; + d = version[i]; + while (std.ascii.isDigit(d)) { + i += 1; + + // patch is done and at input end, valid + if (i >= version.len) return pinned; + d = version[i]; + } + + // Skip remaining valid pre/build tag characters and whitespace. + // Does not validate whitespace used inside pre/build tags. + if (!validPreOrBuildTagCharacter(d) or std.ascii.isWhitespace(d)) return .major; + i += 1; + + // at this point the semver is valid so we can return true if it ends + if (i >= version.len) return pinned; + d = version[i]; + while (validPreOrBuildTagCharacter(d) and !std.ascii.isWhitespace(d)) { + i += 1; + if (i >= version.len) return pinned; + d = version[i]; + } + + // We've come across a character that is not valid for tags or is whitespace. + // Trailing whitespace was trimmed so we can assume there's another range + return .major; + } + + fn validPreOrBuildTagCharacter(c: u8) bool { + return switch (c) { + '-', '+', '.', 'A'...'Z', 'a'...'z', '0'...'9' => true, + else => false, + }; + } + + pub fn isTaggedVersionOnly(input: []const u8) bool { + const version = strings.trim(input, &strings.whitespace_chars); + + // first needs to be a-z + if (version.len == 0 or !std.ascii.isAlphabetic(version[0])) return false; + + for (1..version.len) |i| { + if (!std.ascii.isAlphanumeric(version[i])) return false; + } + + return true; + } + + pub fn orderWithoutTag( + lhs: Version, + rhs: Version, + ) std.math.Order { + if (lhs.major < rhs.major) return .lt; + if (lhs.major > rhs.major) return .gt; + if (lhs.minor < rhs.minor) return .lt; + if (lhs.minor > rhs.minor) return .gt; + if (lhs.patch < rhs.patch) return .lt; + if (lhs.patch > rhs.patch) return .gt; + + if (lhs.tag.hasPre()) { + if (!rhs.tag.hasPre()) return .lt; + } else { + if (rhs.tag.hasPre()) return .gt; + } + + return .eq; + } + + pub fn order( + lhs: Version, + rhs: Version, + lhs_buf: []const u8, + rhs_buf: []const u8, + ) std.math.Order { + const order_without_tag = orderWithoutTag(lhs, rhs); + if (order_without_tag != .eq) return order_without_tag; + + return lhs.tag.order(rhs.tag, lhs_buf, rhs_buf); + } + + pub fn orderWithoutBuild( + lhs: Version, + rhs: Version, + lhs_buf: []const u8, + rhs_buf: []const u8, + ) std.math.Order { + const order_without_tag = orderWithoutTag(lhs, rhs); + if (order_without_tag != .eq) return order_without_tag; + + return lhs.tag.orderWithoutBuild(rhs.tag, lhs_buf, rhs_buf); + } + + pub const Tag = extern struct { + pre: ExternalString = ExternalString{}, + build: ExternalString = ExternalString{}, + + pub fn orderPre(lhs: Tag, rhs: Tag, lhs_buf: []const u8, rhs_buf: []const u8) std.math.Order { + const lhs_str = lhs.pre.slice(lhs_buf); + const rhs_str = rhs.pre.slice(rhs_buf); + + // 1. split each by '.', iterating through each one looking for integers + // 2. compare as integers, or if not possible compare as string + // 3. whichever is greater is the greater one + // + // 1.0.0-canary.0.0.0.0.0.0 < 1.0.0-canary.0.0.0.0.0.1 + + var lhs_itr = strings.split(lhs_str, "."); + var rhs_itr = strings.split(rhs_str, "."); + + while (true) { + const lhs_part = lhs_itr.next(); + const rhs_part = rhs_itr.next(); + + if (lhs_part == null and rhs_part == null) return .eq; + + // if right is null, left is greater than. + if (rhs_part == null) return .gt; + + // if left is null, left is less than. + if (lhs_part == null) return .lt; + + const lhs_uint: ?u32 = std.fmt.parseUnsigned(u32, lhs_part.?, 10) catch null; + const rhs_uint: ?u32 = std.fmt.parseUnsigned(u32, rhs_part.?, 10) catch null; + + // a part that doesn't parse as an integer is greater than a part that does + // https://github.com/npm/node-semver/blob/816c7b2cbfcb1986958a290f941eddfd0441139e/internal/identifiers.js#L12 + if (lhs_uint != null and rhs_uint == null) return .lt; + if (lhs_uint == null and rhs_uint != null) return .gt; + + if (lhs_uint == null and rhs_uint == null) { + switch (strings.order(lhs_part.?, rhs_part.?)) { + .eq => { + // continue to the next part + continue; + }, + else => |not_equal| return not_equal, + } + } + + switch (std.math.order(lhs_uint.?, rhs_uint.?)) { + .eq => continue, + else => |not_equal| return not_equal, + } + } + + unreachable; + } + + pub fn order( + lhs: Tag, + rhs: Tag, + lhs_buf: []const u8, + rhs_buf: []const u8, + ) std.math.Order { + if (!lhs.pre.isEmpty() and !rhs.pre.isEmpty()) { + return lhs.orderPre(rhs, lhs_buf, rhs_buf); + } + + const pre_order = lhs.pre.order(&rhs.pre, lhs_buf, rhs_buf); + if (pre_order != .eq) return pre_order; + + return lhs.build.order(&rhs.build, lhs_buf, rhs_buf); + } + + pub fn orderWithoutBuild( + lhs: Tag, + rhs: Tag, + lhs_buf: []const u8, + rhs_buf: []const u8, + ) std.math.Order { + if (!lhs.pre.isEmpty() and !rhs.pre.isEmpty()) { + return lhs.orderPre(rhs, lhs_buf, rhs_buf); + } + + return lhs.pre.order(&rhs.pre, lhs_buf, rhs_buf); + } + + pub fn cloneInto(this: Tag, slice: []const u8, buf: *[]u8) Tag { + var pre: String = this.pre.value; + var build: String = this.build.value; + + if (this.pre.isInline()) { + pre = this.pre.value; + } else { + const pre_slice = this.pre.slice(slice); + bun.copy(u8, buf.*, pre_slice); + pre = String.init(buf.*, buf.*[0..pre_slice.len]); + buf.* = buf.*[pre_slice.len..]; + } + + if (this.build.isInline()) { + build = this.build.value; + } else { + const build_slice = this.build.slice(slice); + bun.copy(u8, buf.*, build_slice); + build = String.init(buf.*, buf.*[0..build_slice.len]); + buf.* = buf.*[build_slice.len..]; + } + + return .{ + .pre = .{ + .value = pre, + .hash = this.pre.hash, + }, + .build = .{ + .value = build, + .hash = this.build.hash, + }, + }; + } + + pub inline fn hasPre(this: Tag) bool { + return !this.pre.isEmpty(); + } + + pub inline fn hasBuild(this: Tag) bool { + return !this.build.isEmpty(); + } + + pub fn eql(lhs: Tag, rhs: Tag) bool { + return lhs.pre.hash == rhs.pre.hash; + } + + pub const TagResult = struct { + tag: Tag = Tag{}, + len: u32 = 0, + }; + + var multi_tag_warn = false; + // TODO: support multiple tags + + pub fn parse(sliced_string: SlicedString) TagResult { + return parseWithPreCount(sliced_string, 0); + } + + pub fn parseWithPreCount(sliced_string: SlicedString, initial_pre_count: u32) TagResult { + var input = sliced_string.slice; + var build_count: u32 = 0; + var pre_count: u32 = initial_pre_count; + + for (input) |c| { + switch (c) { + ' ' => break, + '+' => { + build_count += 1; + }, + '-' => { + pre_count += 1; + }, + else => {}, + } + } + + if (build_count == 0 and pre_count == 0) { + return TagResult{ + .len = 0, + }; + } + + const State = enum { none, pre, build }; + var result = TagResult{}; + // Common case: no allocation is necessary. + var state = State.none; + var start: usize = 0; + + var i: usize = 0; + + while (i < input.len) : (i += 1) { + const c = input[i]; + switch (c) { + '+' => { + // qualifier ::= ( '-' pre )? ( '+' build )? + if (state == .pre or state == .none and initial_pre_count > 0) { + result.tag.pre = sliced_string.sub(input[start..i]).external(); + } + + if (state != .build) { + state = .build; + start = i + 1; + } + }, + '-' => { + if (state != .pre) { + state = .pre; + start = i + 1; + } + }, + + // only continue if character is a valid pre/build tag character + // https://semver.org/#spec-item-9 + 'a'...'z', 'A'...'Z', '0'...'9', '.' => {}, + + else => { + switch (state) { + .none => {}, + .pre => { + result.tag.pre = sliced_string.sub(input[start..i]).external(); + + state = State.none; + }, + .build => { + result.tag.build = sliced_string.sub(input[start..i]).external(); + if (comptime Environment.isDebug) { + assert(!strings.containsChar(result.tag.build.slice(sliced_string.buf), '-')); + } + state = State.none; + }, + } + result.len = @truncate(i); + break; + }, + } + } + + if (state == .none and initial_pre_count > 0) { + state = .pre; + start = 0; + } + + switch (state) { + .none => {}, + .pre => { + result.tag.pre = sliced_string.sub(input[start..i]).external(); + // a pre can contain multiple consecutive tags + // checking for "-" prefix is not enough, as --canary.67e7966.0 is a valid tag + state = State.none; + }, + .build => { + // a build can contain multiple consecutive tags + result.tag.build = sliced_string.sub(input[start..i]).external(); + + state = State.none; + }, + } + result.len = @as(u32, @truncate(i)); + + return result; + } + }; + + pub const ParseResult = struct { + wildcard: Query.Token.Wildcard = .none, + valid: bool = true, + version: Version.Partial = .{}, + len: u32 = 0, + }; + + pub fn parse(sliced_string: SlicedString) ParseResult { + var input = sliced_string.slice; + var result = ParseResult{}; + + var part_i: u8 = 0; + var part_start_i: usize = 0; + var last_char_i: usize = 0; + + if (input.len == 0) { + result.valid = false; + return result; + } + var is_done = false; + + var i: usize = 0; + + for (0..input.len) |c| { + switch (input[c]) { + // newlines & whitespace + ' ', + '\t', + '\n', + '\r', + std.ascii.control_code.vt, + std.ascii.control_code.ff, + + // version separators + 'v', + '=', + => {}, + else => { + i = c; + break; + }, + } + } + + if (i == input.len) { + result.valid = false; + return result; + } + + // two passes :( + while (i < input.len) { + if (is_done) { + break; + } + + switch (input[i]) { + ' ' => { + is_done = true; + break; + }, + '|', '^', '#', '&', '%', '!' => { + is_done = true; + if (i > 0) { + i -= 1; + } + break; + }, + '0'...'9' => { + part_start_i = i; + i += 1; + + while (i < input.len and switch (input[i]) { + '0'...'9' => true, + else => false, + }) { + i += 1; + } + + last_char_i = i; + + switch (part_i) { + 0 => { + result.version.major = parseVersionNumber(input[part_start_i..last_char_i]); + part_i = 1; + }, + 1 => { + result.version.minor = parseVersionNumber(input[part_start_i..last_char_i]); + part_i = 2; + }, + 2 => { + result.version.patch = parseVersionNumber(input[part_start_i..last_char_i]); + part_i = 3; + }, + else => {}, + } + + if (i < input.len and switch (input[i]) { + // `.` is expected only if there are remaining core version numbers + '.' => part_i != 3, + else => false, + }) { + i += 1; + } + }, + '.' => { + result.valid = false; + is_done = true; + break; + }, + '-', '+' => { + // Just a plain tag with no version is invalid. + if (part_i < 2 and result.wildcard == .none) { + result.valid = false; + is_done = true; + break; + } + + part_start_i = i; + while (i < input.len and switch (input[i]) { + ' ' => true, + else => false, + }) { + i += 1; + } + const tag_result = Tag.parse(sliced_string.sub(input[part_start_i..])); + result.version.tag = tag_result.tag; + i += tag_result.len; + break; + }, + 'x', '*', 'X' => { + part_start_i = i; + i += 1; + + while (i < input.len and switch (input[i]) { + 'x', '*', 'X' => true, + else => false, + }) { + i += 1; + } + + last_char_i = i; + + if (i < input.len and switch (input[i]) { + '.' => true, + else => false, + }) { + i += 1; + } + + if (result.wildcard == .none) { + switch (part_i) { + 0 => { + result.wildcard = Query.Token.Wildcard.major; + part_i = 1; + }, + 1 => { + result.wildcard = Query.Token.Wildcard.minor; + part_i = 2; + }, + 2 => { + result.wildcard = Query.Token.Wildcard.patch; + part_i = 3; + }, + else => {}, + } + } + }, + else => |c| { + + // Some weirdo npm packages in the wild have a version like "1.0.0rc.1" + // npm just expects that to work...even though it has no "-" qualifier. + if (result.wildcard == .none and part_i >= 2 and switch (c) { + 'a'...'z', 'A'...'Z' => true, + else => false, + }) { + part_start_i = i; + const tag_result = Tag.parseWithPreCount(sliced_string.sub(input[part_start_i..]), 1); + result.version.tag = tag_result.tag; + i += tag_result.len; + is_done = true; + last_char_i = i; + break; + } + + last_char_i = 0; + result.valid = false; + is_done = true; + break; + }, + } + } + + if (result.wildcard == .none) { + switch (part_i) { + 0 => { + result.wildcard = Query.Token.Wildcard.major; + }, + 1 => { + result.wildcard = Query.Token.Wildcard.minor; + }, + 2 => { + result.wildcard = Query.Token.Wildcard.patch; + }, + else => {}, + } + } + + result.len = @as(u32, @intCast(i)); + + return result; + } + + fn parseVersionNumber(input: string) ?u32 { + // max decimal u32 is 4294967295 + var bytes: [10]u8 = undefined; + var byte_i: u8 = 0; + + assert(input[0] != '.'); + + for (input) |char| { + switch (char) { + 'X', 'x', '*' => return null, + '0'...'9' => { + // out of bounds + if (byte_i + 1 > bytes.len) return null; + bytes[byte_i] = char; + byte_i += 1; + }, + ' ', '.' => break, + // ignore invalid characters + else => {}, + } + } + + // If there are no numbers + if (byte_i == 0) return null; + + if (comptime Environment.isDebug) { + return std.fmt.parseInt(u32, bytes[0..byte_i], 10) catch |err| { + Output.prettyErrorln("ERROR {s} parsing version: \"{s}\", bytes: {s}", .{ + @errorName(err), + input, + bytes[0..byte_i], + }); + return 0; + }; + } + + return std.fmt.parseInt(u32, bytes[0..byte_i], 10) catch 0; + } +}; + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const bun = @import("root").bun; +const string = bun.string; +const Output = bun.Output; +const Global = bun.Global; +const Environment = bun.Environment; +const strings = bun.strings; +const MutableString = bun.MutableString; +const stringZ = bun.stringZ; +const default_allocator = bun.default_allocator; +const C = bun.C; +const JSC = bun.JSC; +const IdentityContext = @import("../identity_context.zig").IdentityContext; +const OOM = bun.OOM; +const TruncatedPackageNameHash = bun.install.TruncatedPackageNameHash; +const Lockfile = bun.install.Lockfile; +const ExternalString = bun.Semver.ExternalString; +const SlicedString = bun.Semver.SlicedString; +const String = bun.Semver.String; + +const Query = bun.Semver.Query; +const assert = bun.assert; diff --git a/src/shell/interpreter.zig b/src/shell/interpreter.zig index f515e175c67036..d2a08a3f4d869a 100644 --- a/src/shell/interpreter.zig +++ b/src/shell/interpreter.zig @@ -1792,18 +1792,15 @@ pub const Interpreter = struct { } pub fn hasPendingActivity(this: *ThisInterpreter) bool { - @fence(.seq_cst); return this.has_pending_activity.load(.seq_cst) > 0; } fn incrPendingActivityFlag(has_pending_activity: *std.atomic.Value(u32)) void { - @fence(.seq_cst); _ = has_pending_activity.fetchAdd(1, .seq_cst); log("Interpreter incr pending activity {d}", .{has_pending_activity.load(.seq_cst)}); } fn decrPendingActivityFlag(has_pending_activity: *std.atomic.Value(u32)) void { - @fence(.seq_cst); _ = has_pending_activity.fetchSub(1, .seq_cst); log("Interpreter decr pending activity {d}", .{has_pending_activity.load(.seq_cst)}); } @@ -5338,9 +5335,9 @@ pub const Interpreter = struct { const Blob = struct { ref_count: usize = 1, blob: bun.JSC.WebCore.Blob, - pub usingnamespace bun.NewRefCounted(Blob, Blob.deinit); + pub usingnamespace bun.NewRefCounted(Blob, _deinit, null); - pub fn deinit(this: *Blob) void { + fn _deinit(this: *Blob) void { this.blob.deinit(); bun.destroy(this); } @@ -5680,7 +5677,7 @@ pub const Interpreter = struct { } /// If the stdout/stderr is supposed to be captured then get the bytelist associated with that - pub fn stdBufferedBytelist(this: *Builtin, comptime io_kind: @Type(.EnumLiteral)) ?*bun.ByteList { + pub fn stdBufferedBytelist(this: *Builtin, comptime io_kind: @Type(.enum_literal)) ?*bun.ByteList { if (comptime io_kind != .stdout and io_kind != .stderr) { @compileError("Bad IO" ++ @tagName(io_kind)); } @@ -5702,7 +5699,7 @@ pub const Interpreter = struct { } /// **WARNING** You should make sure that stdout/stderr does not need IO (e.g. `.needsIO(.stderr)` is false before caling `.writeNoIO(.stderr, buf)`) - pub fn writeNoIO(this: *Builtin, comptime io_kind: @Type(.EnumLiteral), buf: []const u8) Maybe(usize) { + pub fn writeNoIO(this: *Builtin, comptime io_kind: @Type(.enum_literal), buf: []const u8) Maybe(usize) { if (comptime io_kind != .stdout and io_kind != .stderr) { @compileError("Bad IO" ++ @tagName(io_kind)); } @@ -6368,8 +6365,8 @@ pub const Interpreter = struct { var node_fs = JSC.Node.NodeFS{}; const milliseconds: f64 = @floatFromInt(std.time.milliTimestamp()); const atime: JSC.Node.TimeLike = if (bun.Environment.isWindows) milliseconds / 1000.0 else JSC.Node.TimeLike{ - .tv_sec = @intFromFloat(@divFloor(milliseconds, std.time.ms_per_s)), - .tv_nsec = @intFromFloat(@mod(milliseconds, std.time.ms_per_s) * std.time.ns_per_ms), + .sec = @intFromFloat(@divFloor(milliseconds, std.time.ms_per_s)), + .nsec = @intFromFloat(@mod(milliseconds, std.time.ms_per_s) * std.time.ns_per_ms), }; const mtime = atime; const args = JSC.Node.Arguments.Utimes{ @@ -6906,7 +6903,7 @@ pub const Interpreter = struct { } }; - pub fn writeOutput(this: *Export, comptime io_kind: @Type(.EnumLiteral), comptime fmt: []const u8, args: anytype) Maybe(void) { + pub fn writeOutput(this: *Export, comptime io_kind: @Type(.enum_literal), comptime fmt: []const u8, args: anytype) Maybe(void) { if (this.bltn.stdout.needsIO()) |safeguard| { var output: *BuiltinIO.Output = &@field(this.bltn, @tagName(io_kind)); this.printing = true; @@ -8733,16 +8730,14 @@ pub const Interpreter = struct { } }, - fn incrementOutputCount(this: *@This(), comptime thevar: @Type(.EnumLiteral)) void { - @fence(.seq_cst); + fn incrementOutputCount(this: *@This(), comptime thevar: @Type(.enum_literal)) void { var atomicvar = &@field(this, @tagName(thevar)); const result = atomicvar.fetchAdd(1, .seq_cst); log("[rm] {s}: {d} + 1", .{ @tagName(thevar), result }); return; } - fn getOutputCount(this: *@This(), comptime thevar: @Type(.EnumLiteral)) usize { - @fence(.seq_cst); + fn getOutputCount(this: *@This(), comptime thevar: @Type(.enum_literal)) usize { var atomicvar = &@field(this, @tagName(thevar)); return atomicvar.load(.seq_cst); } @@ -10109,8 +10104,8 @@ pub const Interpreter = struct { bltn: *Builtin, state: enum { idle, waiting_io, err, done } = .idle, buf: std.ArrayListUnmanaged(u8) = .{}, - start: f32 = 1, - end: f32 = 1, + _start: f32 = 1, + _end: f32 = 1, increment: f32 = 1, separator: string = "\n", terminator: string = "", @@ -10155,27 +10150,27 @@ pub const Interpreter = struct { const maybe1 = iter.next().?; const int1 = bun.fmt.parseFloat(f32, bun.sliceTo(maybe1, 0)) catch return this.fail("seq: invalid argument\n"); - this.end = int1; - if (this.start > this.end) this.increment = -1; + this._end = int1; + if (this._start > this._end) this.increment = -1; const maybe2 = iter.next(); if (maybe2 == null) return this.do(); const int2 = bun.fmt.parseFloat(f32, bun.sliceTo(maybe2.?, 0)) catch return this.fail("seq: invalid argument\n"); - this.start = int1; - this.end = int2; - if (this.start < this.end) this.increment = 1; - if (this.start > this.end) this.increment = -1; + this._start = int1; + this._end = int2; + if (this._start < this._end) this.increment = 1; + if (this._start > this._end) this.increment = -1; const maybe3 = iter.next(); if (maybe3 == null) return this.do(); const int3 = bun.fmt.parseFloat(f32, bun.sliceTo(maybe3.?, 0)) catch return this.fail("seq: invalid argument\n"); - this.start = int1; + this._start = int1; this.increment = int2; - this.end = int3; + this._end = int3; if (this.increment == 0) return this.fail("seq: zero increment\n"); - if (this.start > this.end and this.increment > 0) return this.fail("seq: needs negative decrement\n"); - if (this.start < this.end and this.increment < 0) return this.fail("seq: needs positive increment\n"); + if (this._start > this._end and this.increment > 0) return this.fail("seq: needs negative decrement\n"); + if (this._start < this._end and this.increment < 0) return this.fail("seq: needs positive increment\n"); return this.do(); } @@ -10192,11 +10187,11 @@ pub const Interpreter = struct { } fn do(this: *@This()) Maybe(void) { - var current = this.start; + var current = this._start; var arena = std.heap.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); - while (if (this.increment > 0) current <= this.end else current >= this.end) : (current += this.increment) { + while (if (this.increment > 0) current <= this._end else current >= this._end) : (current += this.increment) { const str = std.fmt.allocPrint(arena.allocator(), "{d}", .{current}) catch bun.outOfMemory(); defer _ = arena.reset(.retain_capacity); _ = this.print(str); @@ -11136,8 +11131,7 @@ pub const Interpreter = struct { pub const ChildPtr = IOReaderChildPtr; pub const ReaderImpl = bun.io.BufferedReader; - pub const DEBUG_REFCOUNT_NAME: []const u8 = "IOReaderRefCount"; - pub usingnamespace bun.NewRefCounted(@This(), IOReader.asyncDeinit); + pub usingnamespace bun.NewRefCounted(@This(), asyncDeinit, "IOReaderRefCount"); const InitFlags = packed struct(u8) { pollable: bool = false, @@ -11403,8 +11397,6 @@ pub const Interpreter = struct { started: bool = false, flags: InitFlags = .{}, - pub const DEBUG_REFCOUNT_NAME: []const u8 = "IOWriterRefCount"; - const debug = bun.Output.scoped(.IOWriter, true); const ChildPtr = IOWriterChildPtr; @@ -11416,7 +11408,7 @@ pub const Interpreter = struct { pub const auto_poll = false; - pub usingnamespace bun.NewRefCounted(@This(), asyncDeinit); + pub usingnamespace bun.NewRefCounted(@This(), asyncDeinit, "IOWriterRefCount"); const This = @This(); pub const WriterImpl = bun.io.BufferedWriter( This, @@ -11940,7 +11932,7 @@ pub fn StatePtrUnion(comptime TypesValue: anytype) type { pub fn init(_ptr: anytype) @This() { const tyinfo = @typeInfo(@TypeOf(_ptr)); - if (tyinfo != .Pointer) @compileError("Only pass pointers to StatePtrUnion.init(), you gave us a: " ++ @typeName(@TypeOf(_ptr))); + if (tyinfo != .pointer) @compileError("Only pass pointers to StatePtrUnion.init(), you gave us a: " ++ @typeName(@TypeOf(_ptr))); const Type = std.meta.Child(@TypeOf(_ptr)); Ptr.assert_type(Type); @@ -11957,7 +11949,7 @@ pub fn MaybeChild(comptime T: type) type { return switch (@typeInfo(T)) { .Array => |info| info.child, .Vector => |info| info.child, - .Pointer => |info| info.child, + .pointer => |info| info.child, .Optional => |info| info.child, else => T, }; @@ -12089,8 +12081,8 @@ inline fn errnocast(errno: anytype) u16 { inline fn fastMod(val: anytype, comptime rhs: comptime_int) @TypeOf(val) { const Value = @typeInfo(@TypeOf(val)); - if (Value != .Int) @compileError("LHS of fastMod should be an int"); - if (Value.Int.signedness != .unsigned) @compileError("LHS of fastMod should be unsigned"); + if (Value != .int) @compileError("LHS of fastMod should be an int"); + if (Value.int.signedness != .unsigned) @compileError("LHS of fastMod should be unsigned"); if (!comptime std.math.isPowerOfTwo(rhs)) @compileError("RHS of fastMod should be power of 2"); return val & (rhs - 1); @@ -12242,7 +12234,7 @@ const ShellSyscall = struct { return Syscall.fstatat(dir, path_); } - fn openat(dir: bun.FileDescriptor, path: [:0]const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { + fn openat(dir: bun.FileDescriptor, path: [:0]const u8, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { if (bun.Environment.isWindows) { if (flags & bun.O.DIRECTORY != 0) { if (ResolvePath.Platform.posix.isAbsolute(path[0..path.len])) { diff --git a/src/shell/shell.zig b/src/shell/shell.zig index 6133dc62c17935..ce13900af1a05a 100644 --- a/src/shell/shell.zig +++ b/src/shell/shell.zig @@ -165,7 +165,7 @@ pub const ParseError = error{ Lex, }; -extern "C" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: i32) i32; +extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: i32) i32; fn setEnv(name: [*:0]const u8, value: [*:0]const u8) void { // TODO: windows @@ -226,7 +226,7 @@ pub const GlobalJS = struct { }; } - pub inline fn createNullDelimitedEnvMap(this: @This(), alloc: Allocator) ![:null]?[*:0]u8 { + pub inline fn createNullDelimitedEnvMap(this: @This(), alloc: Allocator) ![:null]?[*:0]const u8 { return this.globalThis.bunVM().transpiler.env.map.createNullDelimitedEnvMap(alloc); } @@ -298,7 +298,7 @@ pub const GlobalMini = struct { }; } - pub inline fn createNullDelimitedEnvMap(this: @This(), alloc: Allocator) ![:null]?[*:0]u8 { + pub inline fn createNullDelimitedEnvMap(this: @This(), alloc: Allocator) ![:null]?[*:0]const u8 { return this.mini.env.?.map.createNullDelimitedEnvMap(alloc); } @@ -770,10 +770,10 @@ pub const AST = struct { return .{ .stdout = true, .duplicate = true }; } - pub fn toFlags(this: RedirectFlags) bun.Mode { - const read_write_flags: bun.Mode = if (this.stdin) bun.O.RDONLY else bun.O.WRONLY | bun.O.CREAT; - const extra: bun.Mode = if (this.append) bun.O.APPEND else bun.O.TRUNC; - const final_flags: bun.Mode = if (this.stdin) read_write_flags else extra | read_write_flags; + pub fn toFlags(this: RedirectFlags) i32 { + const read_write_flags: i32 = if (this.stdin) bun.O.RDONLY else bun.O.WRONLY | bun.O.CREAT; + const extra: i32 = if (this.append) bun.O.APPEND else bun.O.TRUNC; + const final_flags: i32 = if (this.stdin) read_write_flags else extra | read_write_flags; return final_flags; } @@ -986,7 +986,7 @@ pub const Parser = struct { /// If you make a subparser and call some fallible functions on it, you need to catch the errors and call `.continue_from_subparser()`, otherwise errors /// will not propagate upwards to the parent. pub fn make_subparser(this: *Parser, kind: SubshellKind) Parser { - const subparser = .{ + const subparser: Parser = .{ .strpool = this.strpool, .tokens = this.tokens, .alloc = this.alloc, @@ -1146,7 +1146,7 @@ pub const Parser = struct { return expr; } - fn extractIfClauseTextToken(comptime if_clause_token: @TypeOf(.EnumLiteral)) []const u8 { + fn extractIfClauseTextToken(comptime if_clause_token: @TypeOf(.enum_literal)) []const u8 { const tagname = comptime switch (if_clause_token) { .@"if" => "if", .@"else" => "else", @@ -1158,7 +1158,7 @@ pub const Parser = struct { return tagname; } - fn expectIfClauseTextToken(self: *Parser, comptime if_clause_token: @TypeOf(.EnumLiteral)) Token { + fn expectIfClauseTextToken(self: *Parser, comptime if_clause_token: @TypeOf(.enum_literal)) Token { const tagname = comptime extractIfClauseTextToken(if_clause_token); if (bun.Environment.allow_assert) assert(@as(TokenTag, self.peek()) == .Text); if (self.peek() == .Text and @@ -1172,14 +1172,14 @@ pub const Parser = struct { @panic("Expected: " ++ @tagName(if_clause_token)); } - fn isIfClauseTextToken(self: *Parser, comptime if_clause_token: @TypeOf(.EnumLiteral)) bool { + fn isIfClauseTextToken(self: *Parser, comptime if_clause_token: @TypeOf(.enum_literal)) bool { return switch (self.peek()) { .Text => |range| self.isIfClauseTextTokenImpl(range, if_clause_token), else => false, }; } - fn isIfClauseTextTokenImpl(self: *Parser, range: Token.TextRange, comptime if_clause_token: @TypeOf(.EnumLiteral)) bool { + fn isIfClauseTextTokenImpl(self: *Parser, range: Token.TextRange, comptime if_clause_token: @TypeOf(.enum_literal)) bool { const tagname = comptime extractIfClauseTextToken(if_clause_token); return bun.strings.eqlComptime(self.text(range), tagname); } @@ -2248,7 +2248,7 @@ pub fn NewLexer(comptime encoding: StringEncoding) type { fn make_sublexer(self: *@This(), kind: SubShellKind) @This() { log("[lex] make sublexer", .{}); - var sublexer = .{ + var sublexer: @This() = .{ .chars = self.chars, .strpool = self.strpool, .tokens = self.tokens, @@ -2727,7 +2727,7 @@ pub fn NewLexer(comptime encoding: StringEncoding) type { } fn appendUnicodeCharToStrPool(self: *@This(), char: Chars.CodepointType) !void { - @setCold(true); + @branchHint(.cold); const ichar: i32 = @intCast(char); var bytes: [4]u8 = undefined; diff --git a/src/shell/subproc.zig b/src/shell/subproc.zig index 940e117562ebe4..9ced2d1fa7f91c 100644 --- a/src/shell/subproc.zig +++ b/src/shell/subproc.zig @@ -511,7 +511,7 @@ pub const ShellSubprocess = struct { return this.process.kill(@intCast(sig)); } - // fn hasCalledGetter(this: *Subprocess, comptime getter: @Type(.EnumLiteral)) bool { + // fn hasCalledGetter(this: *Subprocess, comptime getter: @Type(.enum_literal)) bool { // return this.observable_getters.contains(getter); // } @@ -528,7 +528,7 @@ pub const ShellSubprocess = struct { // this.ipc_mode = .none; } - pub fn closeIO(this: *@This(), comptime io: @Type(.EnumLiteral)) void { + pub fn closeIO(this: *@This(), comptime io: @Type(.enum_literal)) void { if (this.closed.contains(io)) return; log("close IO {s}", .{@tagName(io)}); this.closed.insert(io); @@ -1020,7 +1020,7 @@ pub const PipeReader = struct { } }; - pub usingnamespace bun.NewRefCounted(PipeReader, deinit); + pub usingnamespace bun.NewRefCounted(PipeReader, deinit, null); pub const CapturedWriter = struct { dead: bool = true, diff --git a/src/sourcemap/CodeCoverage.zig b/src/sourcemap/CodeCoverage.zig index eeb34112854d2a..2075f1d4c94571 100644 --- a/src/sourcemap/CodeCoverage.zig +++ b/src/sourcemap/CodeCoverage.zig @@ -692,8 +692,7 @@ pub const ByteRangeMapping = struct { return globalThis.throwOutOfMemoryValue(); }; - var str = bun.String.createUTF8(mutable_str.slice()); - return str.transferToJS(globalThis); + return bun.String.createUTF8ForJS(globalThis, mutable_str.slice()); } pub fn compute(source_contents: []const u8, source_id: i32, source_url: bun.JSC.ZigString.Slice) ByteRangeMapping { @@ -707,10 +706,10 @@ pub const ByteRangeMapping = struct { comptime { if (bun.Environment.isNative) { - @export(ByteRangeMapping.generate, .{ .name = "ByteRangeMapping__generate" }); - @export(ByteRangeMapping.findExecutedLines, .{ .name = "ByteRangeMapping__findExecutedLines" }); - @export(ByteRangeMapping.find, .{ .name = "ByteRangeMapping__find" }); - @export(ByteRangeMapping.getSourceID, .{ .name = "ByteRangeMapping__getSourceID" }); + @export(&ByteRangeMapping.generate, .{ .name = "ByteRangeMapping__generate" }); + @export(&ByteRangeMapping.findExecutedLines, .{ .name = "ByteRangeMapping__findExecutedLines" }); + @export(&ByteRangeMapping.find, .{ .name = "ByteRangeMapping__find" }); + @export(&ByteRangeMapping.getSourceID, .{ .name = "ByteRangeMapping__getSourceID" }); } } diff --git a/src/sourcemap/sourcemap.zig b/src/sourcemap/sourcemap.zig index 41ddfd67f13d67..50c37980c19953 100644 --- a/src/sourcemap/sourcemap.zig +++ b/src/sourcemap/sourcemap.zig @@ -640,7 +640,7 @@ pub const ParsedSourceMap = struct { is_standalone_module_graph: bool = false, - pub usingnamespace bun.NewThreadSafeRefCounted(ParsedSourceMap, deinitFn); + pub usingnamespace bun.NewThreadSafeRefCounted(ParsedSourceMap, deinitFn, null); const SourceContentPtr = packed struct(u64) { load_hint: SourceMapLoadHint = .none, diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index 874575f8aeeb8a..01dd450adce4ac 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -45,6 +45,51 @@ pub const AnyPostgresError = error{ UnsupportedIntegerSize, }; +pub fn postgresErrorToJS(globalObject: *JSC.JSGlobalObject, message: ?[]const u8, err: AnyPostgresError) JSValue { + const error_code: JSC.Error = switch (err) { + error.ConnectionClosed => JSC.Error.ERR_POSTGRES_CONNECTION_CLOSED, + error.ExpectedRequest => JSC.Error.ERR_POSTGRES_EXPECTED_REQUEST, + error.ExpectedStatement => JSC.Error.ERR_POSTGRES_EXPECTED_STATEMENT, + error.InvalidBackendKeyData => JSC.Error.ERR_POSTGRES_INVALID_BACKEND_KEY_DATA, + error.InvalidBinaryData => JSC.Error.ERR_POSTGRES_INVALID_BINARY_DATA, + error.InvalidByteSequence => JSC.Error.ERR_POSTGRES_INVALID_BYTE_SEQUENCE, + error.InvalidByteSequenceForEncoding => JSC.Error.ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING, + error.InvalidCharacter => JSC.Error.ERR_POSTGRES_INVALID_CHARACTER, + error.InvalidMessage => JSC.Error.ERR_POSTGRES_INVALID_MESSAGE, + error.InvalidMessageLength => JSC.Error.ERR_POSTGRES_INVALID_MESSAGE_LENGTH, + error.InvalidQueryBinding => JSC.Error.ERR_POSTGRES_INVALID_QUERY_BINDING, + error.InvalidServerKey => JSC.Error.ERR_POSTGRES_INVALID_SERVER_KEY, + error.InvalidServerSignature => JSC.Error.ERR_POSTGRES_INVALID_SERVER_SIGNATURE, + error.MultidimensionalArrayNotSupportedYet => JSC.Error.ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET, + error.NullsInArrayNotSupportedYet => JSC.Error.ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET, + error.Overflow => JSC.Error.ERR_POSTGRES_OVERFLOW, + error.PBKDFD2 => JSC.Error.ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2, + error.SASL_SIGNATURE_MISMATCH => JSC.Error.ERR_POSTGRES_SASL_SIGNATURE_MISMATCH, + error.SASL_SIGNATURE_INVALID_BASE64 => JSC.Error.ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64, + error.TLSNotAvailable => JSC.Error.ERR_POSTGRES_TLS_NOT_AVAILABLE, + error.TLSUpgradeFailed => JSC.Error.ERR_POSTGRES_TLS_UPGRADE_FAILED, + error.UnexpectedMessage => JSC.Error.ERR_POSTGRES_UNEXPECTED_MESSAGE, + error.UNKNOWN_AUTHENTICATION_METHOD => JSC.Error.ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD, + error.UNSUPPORTED_AUTHENTICATION_METHOD => JSC.Error.ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD, + error.UnsupportedByteaFormat => JSC.Error.ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT, + error.UnsupportedIntegerSize => JSC.Error.ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE, + error.JSError => { + return globalObject.takeException(error.JSError); + }, + error.OutOfMemory => { + // TODO: add binding for creating an out of memory error? + return globalObject.takeException(globalObject.throwOutOfMemory()); + }, + error.ShortRead => { + bun.unreachablePanic("Assertion failed: ShortRead should be handled by the caller in postgres", .{}); + }, + }; + if (message) |msg| { + return error_code.fmt(globalObject, "{s}", .{msg}); + } + return error_code.fmt(globalObject, "Failed to bind query: {s}", .{@errorName(err)}); +} + pub const SSLMode = enum(u8) { disable = 0, prefer = 1, @@ -198,10 +243,8 @@ pub const PostgresSQLContext = struct { } comptime { - if (!JSC.is_bindgen) { - const js_init = JSC.toJSHostFunction(init); - @export(js_init, .{ .name = "PostgresSQLContext__init" }); - } + const js_init = JSC.toJSHostFunction(init); + @export(&js_init, .{ .name = "PostgresSQLContext__init" }); } }; pub const PostgresSQLQueryResultMode = enum(u8) { @@ -209,13 +252,71 @@ pub const PostgresSQLQueryResultMode = enum(u8) { values = 1, raw = 2, }; + +const JSRef = union(enum) { + weak: JSC.JSValue, + strong: JSC.Strong, + + pub fn initWeak(value: JSC.JSValue) @This() { + return .{ .weak = value }; + } + + pub fn initStrong(value: JSC.JSValue, globalThis: *JSC.JSGlobalObject) @This() { + return .{ .strong = JSC.Strong.create(value, globalThis) }; + } + + pub fn empty() @This() { + return .{ .weak = .zero }; + } + + pub fn get(this: *@This()) JSC.JSValue { + return switch (this.*) { + .weak => this.weak, + .strong => this.strong.get() orelse .zero, + }; + } + pub fn setWeak(this: *@This(), value: JSC.JSValue) void { + if (this == .strong) { + this.strong.deinit(); + } + this.* = .{ .weak = value }; + } + + pub fn setStrong(this: *@This(), value: JSC.JSValue, globalThis: *JSC.JSGlobalObject) void { + if (this == .strong) { + this.strong.set(globalThis, value); + return; + } + this.* = .{ .strong = JSC.Strong.create(value, globalThis) }; + } + + pub fn upgrade(this: *@This(), globalThis: *JSC.JSGlobalObject) void { + switch (this.*) { + .weak => { + bun.assert(this.weak != .zero); + this.* = .{ .strong = JSC.Strong.create(this.weak, globalThis) }; + }, + .strong => {}, + } + } + + pub fn deinit(this: *@This()) void { + switch (this.*) { + .weak => { + this.weak = .zero; + }, + .strong => { + this.strong.deinit(); + }, + } + } +}; pub const PostgresSQLQuery = struct { statement: ?*PostgresSQLStatement = null, query: bun.String = bun.String.empty, cursor_name: bun.String = bun.String.empty, - // Kept alive by being in the "queries" array from JS. - thisValue: JSValue = .undefined, + thisValue: JSRef = JSRef.empty(), status: Status = Status.pending, @@ -229,26 +330,30 @@ pub const PostgresSQLQuery = struct { } = .{}, pub usingnamespace JSC.Codegen.JSPostgresSQLQuery; - const log = bun.Output.scoped(.PostgresSQLQuery, false); pub fn getTarget(this: *PostgresSQLQuery, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - if (this.thisValue == .zero) { + const thisValue = this.thisValue.get(); + if (thisValue == .zero) { return .zero; } - const target = PostgresSQLQuery.targetGetCached(this.thisValue) orelse return .zero; - PostgresSQLQuery.targetSetCached(this.thisValue, globalObject, .zero); + const target = PostgresSQLQuery.targetGetCached(thisValue) orelse return .zero; + PostgresSQLQuery.targetSetCached(thisValue, globalObject, .zero); return target; } pub const Status = enum(u8) { + /// The query was just enqueued, statement status can be checked for more details pending, - written, - running, + /// The query is being bound to the statement binding, + /// The query is running + running, + /// The query was successful success, + /// The query failed fail, pub fn isRunning(this: Status) bool { - return this == .running or this == .binding; + return @intFromEnum(this) > @intFromEnum(Status.pending) and @intFromEnum(this) < @intFromEnum(Status.success); } }; @@ -257,6 +362,7 @@ pub const PostgresSQLQuery = struct { } pub fn deinit(this: *@This()) void { + this.thisValue.deinit(); if (this.statement) |statement| { statement.deref(); } @@ -267,7 +373,11 @@ pub const PostgresSQLQuery = struct { pub fn finalize(this: *@This()) void { debug("PostgresSQLQuery finalize", .{}); - this.thisValue = .zero; + if (this.thisValue == .weak) { + // clean up if is a weak reference, if is a strong reference we need to wait until the query is done + // if we are a strong reference, here is probably a bug because GC'd should not happen + this.thisValue.weak = .zero; + } this.deref(); } @@ -283,27 +393,6 @@ pub const PostgresSQLQuery = struct { bun.assert(this.ref_count.fetchAdd(1, .monotonic) > 0); } - pub fn onNoData(this: *@This(), globalObject: *JSC.JSGlobalObject, queries_array: JSValue) void { - this.status = .success; - defer this.deref(); - - const thisValue = this.thisValue; - const targetValue = this.getTarget(globalObject); - if (thisValue == .zero or targetValue == .zero) { - return; - } - - const vm = JSC.VirtualMachine.get(); - const function = vm.rareData().postgresql_context.onQueryResolveFn.get().?; - const event_loop = vm.eventLoop(); - event_loop.runCallback(function, globalObject, thisValue, &.{ - targetValue, - this.pending_value.trySwap() orelse .undefined, - JSValue.jsNumber(0), - JSValue.jsNumber(0), - queries_array, - }); - } pub fn onWriteFail( this: *@This(), err: AnyPostgresError, @@ -311,30 +400,29 @@ pub const PostgresSQLQuery = struct { queries_array: JSValue, ) void { this.status = .fail; - const thisValue = this.thisValue; + const thisValue = this.thisValue.get(); + defer this.thisValue.deinit(); const targetValue = this.getTarget(globalObject); if (thisValue == .zero or targetValue == .zero) { return; } - const instance = globalObject.createErrorInstance("Failed to bind query: {s}", .{@errorName(err)}); - - // TODO: error handling const vm = JSC.VirtualMachine.get(); const function = vm.rareData().postgresql_context.onQueryRejectFn.get().?; const event_loop = vm.eventLoop(); event_loop.runCallback(function, globalObject, thisValue, &.{ targetValue, - instance, + postgresErrorToJS(globalObject, null, err), queries_array, }); } - - pub fn onError(this: *@This(), err: protocol.ErrorResponse, globalObject: *JSC.JSGlobalObject) void { + pub fn onJSError(this: *@This(), err: JSC.JSValue, globalObject: *JSC.JSGlobalObject) void { this.status = .fail; + this.ref(); defer this.deref(); - const thisValue = this.thisValue; + const thisValue = this.thisValue.get(); + defer this.thisValue.deinit(); const targetValue = this.getTarget(globalObject); if (thisValue == .zero or targetValue == .zero) { return; @@ -345,9 +433,12 @@ pub const PostgresSQLQuery = struct { const event_loop = vm.eventLoop(); event_loop.runCallback(function, globalObject, thisValue, &.{ targetValue, - err.toJS(globalObject), + err, }); } + pub fn onError(this: *@This(), err: PostgresSQLStatement.Error, globalObject: *JSC.JSGlobalObject) void { + this.onJSError(err.toJS(globalObject), globalObject); + } const CommandTag = union(enum) { // For an INSERT command, the tag is INSERT oid rows, where rows is the @@ -466,9 +557,11 @@ pub const PostgresSQLQuery = struct { pub fn onSuccess(this: *@This(), command_tag_str: []const u8, globalObject: *JSC.JSGlobalObject, connection: JSC.JSValue) void { this.status = .success; + this.ref(); defer this.deref(); - const thisValue = this.thisValue; + const thisValue = this.thisValue.get(); + defer this.thisValue.deinit(); const targetValue = this.getTarget(globalObject); defer allowGC(thisValue, globalObject); if (thisValue == .zero or targetValue == .zero) { @@ -535,12 +628,11 @@ pub const PostgresSQLQuery = struct { ptr.* = .{ .query = query.toBunString(globalThis), - .thisValue = this_value, + .thisValue = JSRef.initWeak(this_value), .flags = .{ .bigint = bigint, }, }; - ptr.query.ref(); PostgresSQLQuery.bindingSetCached(this_value, globalThis, values); PostgresSQLQuery.pendingValueSetCached(this_value, globalThis, pending_value); @@ -579,6 +671,7 @@ pub const PostgresSQLQuery = struct { const connection: *PostgresSQLConnection = arguments[0].as(PostgresSQLConnection) orelse { return globalObject.throw("connection must be a PostgresSQLConnection", .{}); }; + connection.poll_ref.ref(globalObject.bunVM()); var query = arguments[1]; @@ -606,79 +699,91 @@ pub const PostgresSQLQuery = struct { const has_params = signature.fields.len > 0; var did_write = false; - enqueue: { if (entry.found_existing) { this.statement = entry.value_ptr.*; this.statement.?.ref(); signature.deinit(); - if (has_params and this.statement.?.status == .parsing) { + switch (this.statement.?.status) { + .failed => { + // If the statement failed, we need to throw the error + return globalObject.throwValue(this.statement.?.error_response.?.toJS(globalObject)); + }, + .prepared => { + if (!connection.hasQueryRunning()) { + this.flags.binary = this.statement.?.fields.len > 0; + debug("bindAndExecute", .{}); + // 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| { + if (!globalObject.hasException()) + return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to bind and execute query", err)); + return error.JSError; + }; + this.status = .binding; - // if it has params, we need to wait for ParamDescription to be received before we can write the data - } else { - this.flags.binary = this.statement.?.fields.len > 0; - log("bindAndExecute", .{}); - PostgresRequest.bindAndExecute(globalObject, this.statement.?, binding_value, columns_value, PostgresSQLConnection.Writer, writer) catch |err| { - if (!globalObject.hasException()) - return globalObject.throwError(err, "failed to bind and execute query"); - return error.JSError; - }; - did_write = true; + did_write = true; + } + }, + .parsing, .pending => {}, } break :enqueue; } - // If it does not have params, we can write and execute immediately in one go - if (!has_params) { - log("prepareAndQueryWithSignature", .{}); + const can_execute = !connection.hasQueryRunning(); - PostgresRequest.prepareAndQueryWithSignature(globalObject, query_str.slice(), binding_value, PostgresSQLConnection.Writer, writer, &signature) catch |err| { - signature.deinit(); - if (!globalObject.hasException()) - return globalObject.throwError(err, "failed to prepare and query"); - return error.JSError; - }; - did_write = true; - } else { - log("writeQuery", .{}); - - PostgresRequest.writeQuery(query_str.slice(), signature.prepared_statement_name, signature.fields, PostgresSQLConnection.Writer, writer) catch |err| { - signature.deinit(); - if (!globalObject.hasException()) - return globalObject.throwError(err, "failed to write query"); - return error.JSError; - }; - writer.write(&protocol.Sync) catch |err| { - signature.deinit(); - if (!globalObject.hasException()) - return globalObject.throwError(err, "failed to flush"); - return error.JSError; - }; + if (can_execute) { + // If it does not have params, we can write and execute immediately in one go + if (!has_params) { + debug("prepareAndQueryWithSignature", .{}); + // 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 (!globalObject.hasException()) + return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to prepare and query", err)); + return error.JSError; + }; + this.status = .binding; + did_write = true; + } else { + debug("writeQuery", .{}); + PostgresRequest.writeQuery(query_str.slice(), signature.prepared_statement_name, signature.fields, PostgresSQLConnection.Writer, writer) catch |err| { + signature.deinit(); + if (!globalObject.hasException()) + return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to write query", err)); + return error.JSError; + }; + writer.write(&protocol.Sync) catch |err| { + signature.deinit(); + if (!globalObject.hasException()) + return globalObject.throwValue(postgresErrorToJS(globalObject, "failed to flush", err)); + return error.JSError; + }; + did_write = true; + } } - { - const stmt = bun.default_allocator.create(PostgresSQLStatement) catch |err| { - return globalObject.throwError(err, "failed to allocate statement"); + const stmt = bun.default_allocator.create(PostgresSQLStatement) catch { + return globalObject.throwOutOfMemory(); }; connection.prepared_statement_id += 1; - stmt.* = .{ .signature = signature, .ref_count = 2, .status = PostgresSQLStatement.Status.parsing }; + stmt.* = .{ .signature = signature, .ref_count = 2, .status = if (can_execute) .parsing else .pending }; this.statement = stmt; entry.value_ptr.* = stmt; } } - - connection.requests.writeItem(this) catch {}; + // 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.status = if (did_write) .binding else .pending; - PostgresSQLQuery.targetSetCached(this_value, globalObject, query); + this.thisValue.upgrade(globalObject); - if (connection.is_ready_for_query) - connection.flushDataAndResetTimeout() - else if (did_write) + PostgresSQLQuery.targetSetCached(this_value, globalObject, query); + if (did_write) { + connection.flushDataAndResetTimeout(); + } else { connection.resetConnectionTimeout(); - + } return .undefined; } @@ -691,10 +796,8 @@ pub const PostgresSQLQuery = struct { } comptime { - if (!JSC.is_bindgen) { - const jscall = JSC.toJSHostFunction(call); - @export(jscall, .{ .name = "PostgresSQLQuery__createInstance" }); - } + const jscall = JSC.toJSHostFunction(call); + @export(&jscall, .{ .name = "PostgresSQLQuery__createInstance" }); } }; @@ -773,7 +876,7 @@ pub const PostgresRequest = struct { continue; } if (comptime bun.Environment.enable_logs) { - debug(" -> {s}", .{tag.name() orelse "(unknown)"}); + debug(" -> {s}", .{tag.tagName() orelse "(unknown)"}); } switch ( @@ -940,8 +1043,9 @@ pub const PostgresRequest = struct { ) !void { while (true) { reader.markMessageStart(); - - switch (try reader.int(u8)) { + const c = try reader.int(u8); + debug("read: {c}", .{c}); + switch (c) { 'D' => try connection.on(.DataRow, Context, reader), 'd' => try connection.on(.CopyData, Context, reader), 'S' => { @@ -985,9 +1089,10 @@ pub const PostgresRequest = struct { 'c' => try connection.on(.CopyDone, Context, reader), 'W' => try connection.on(.CopyBothResponse, Context, reader), - else => |c| { - debug("Unknown message: {d}", .{c}); + else => { + debug("Unknown message: {c}", .{c}); const to_skip = try reader.length() -| 1; + debug("to_skip: {d}", .{to_skip}); try reader.skip(@intCast(@max(to_skip, 0))); }, } @@ -1015,13 +1120,9 @@ pub const PostgresSQLConnection = struct { pending_activity_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(0), js_value: JSValue = JSValue.undefined, - is_ready_for_query: bool = false, - backend_parameters: bun.StringMap = bun.StringMap.init(bun.default_allocator, true), backend_key_data: protocol.BackendKeyData = .{}, - pending_disconnect: bool = false, - database: []const u8 = "", user: []const u8 = "", password: []const u8 = "", @@ -1038,6 +1139,8 @@ pub const PostgresSQLConnection = struct { idle_timeout_interval_ms: u32 = 0, connection_timeout_ms: u32 = 0, + flags: ConnectionFlags = .{}, + /// Before being connected, this is a connection timeout timer. /// After being connected, this is an idle timeout timer. timer: JSC.BunTimer.EventLoopTimer = .{ @@ -1060,6 +1163,11 @@ pub const PostgresSQLConnection = struct { }, }, + pub const ConnectionFlags = packed struct { + is_ready_for_query: bool = false, + is_processing_data: bool = false, + }; + pub const TLSStatus = union(enum) { none, pending, @@ -1196,8 +1304,15 @@ pub const PostgresSQLConnection = struct { else => this.connection_timeout_ms, }; } - + pub fn disableConnectionTimeout(this: *PostgresSQLConnection) void { + if (this.timer.state == .ACTIVE) { + this.globalObject.bunVM().timer.remove(&this.timer); + } + this.timer.state = .CANCELLED; + } pub fn resetConnectionTimeout(this: *PostgresSQLConnection) void { + // if we are processing data, don't reset the timeout, wait for the data to be processed + if (this.flags.is_processing_data) return; const interval = this.getTimeoutInterval(); if (this.timer.state == .ACTIVE) { this.globalObject.bunVM().timer.remove(&this.timer); @@ -1273,7 +1388,12 @@ pub const PostgresSQLConnection = struct { pub fn onConnectionTimeout(this: *PostgresSQLConnection) JSC.BunTimer.EventLoopTimer.Arm { debug("onConnectionTimeout", .{}); + this.timer.state = .FIRED; + if (this.flags.is_processing_data) { + return .disarm; + } + if (this.getTimeoutInterval() == 0) { this.resetConnectionTimeout(); return .disarm; @@ -1313,21 +1433,18 @@ pub const PostgresSQLConnection = struct { } pub fn hasPendingActivity(this: *PostgresSQLConnection) bool { - @fence(.acquire); return this.pending_activity_count.load(.acquire) > 0; } fn updateHasPendingActivity(this: *PostgresSQLConnection) void { - @fence(.release); const a: u32 = if (this.requests.readableLength() > 0) 1 else 0; const b: u32 = if (this.status != .disconnected) 1 else 0; this.pending_activity_count.store(a + b, .release); } pub fn setStatus(this: *PostgresSQLConnection, status: Status) void { - defer this.updateHasPendingActivity(); - if (this.status == status) return; + defer this.updateHasPendingActivity(); this.status = status; this.resetConnectionTimeout(); @@ -1339,7 +1456,6 @@ pub const PostgresSQLConnection = struct { js_value.ensureStillAlive(); this.globalObject.queueMicrotask(on_connect, &[_]JSValue{ JSValue.jsNull(), js_value }); this.poll_ref.unref(this.globalObject.bunVM()); - this.updateHasPendingActivity(); }, else => {}, } @@ -1376,7 +1492,8 @@ pub const PostgresSQLConnection = struct { this.ref(); defer this.deref(); - this.refAndClose(); + // we defer the refAndClose so the on_close will be called first before we reject the pending requests + defer this.refAndClose(value); const on_close = this.consumeOnCloseCallback(this.globalObject) orelse return; const loop = this.globalObject.bunVM().eventLoop(); @@ -1400,47 +1517,8 @@ pub const PostgresSQLConnection = struct { debug("failed: {s}: {s}", .{ message, @errorName(err) }); const globalObject = this.globalObject; - const error_code: JSC.Error = switch (err) { - error.ConnectionClosed => JSC.Error.ERR_POSTGRES_CONNECTION_CLOSED, - error.ExpectedRequest => JSC.Error.ERR_POSTGRES_EXPECTED_REQUEST, - error.ExpectedStatement => JSC.Error.ERR_POSTGRES_EXPECTED_STATEMENT, - error.InvalidBackendKeyData => JSC.Error.ERR_POSTGRES_INVALID_BACKEND_KEY_DATA, - error.InvalidBinaryData => JSC.Error.ERR_POSTGRES_INVALID_BINARY_DATA, - error.InvalidByteSequence => JSC.Error.ERR_POSTGRES_INVALID_BYTE_SEQUENCE, - error.InvalidByteSequenceForEncoding => JSC.Error.ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING, - error.InvalidCharacter => JSC.Error.ERR_POSTGRES_INVALID_CHARACTER, - error.InvalidMessage => JSC.Error.ERR_POSTGRES_INVALID_MESSAGE, - error.InvalidMessageLength => JSC.Error.ERR_POSTGRES_INVALID_MESSAGE_LENGTH, - error.InvalidQueryBinding => JSC.Error.ERR_POSTGRES_INVALID_QUERY_BINDING, - error.InvalidServerKey => JSC.Error.ERR_POSTGRES_INVALID_SERVER_KEY, - error.InvalidServerSignature => JSC.Error.ERR_POSTGRES_INVALID_SERVER_SIGNATURE, - error.MultidimensionalArrayNotSupportedYet => JSC.Error.ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET, - error.NullsInArrayNotSupportedYet => JSC.Error.ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET, - error.Overflow => JSC.Error.ERR_POSTGRES_OVERFLOW, - error.PBKDFD2 => JSC.Error.ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2, - error.SASL_SIGNATURE_MISMATCH => JSC.Error.ERR_POSTGRES_SASL_SIGNATURE_MISMATCH, - error.SASL_SIGNATURE_INVALID_BASE64 => JSC.Error.ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64, - error.TLSNotAvailable => JSC.Error.ERR_POSTGRES_TLS_NOT_AVAILABLE, - error.TLSUpgradeFailed => JSC.Error.ERR_POSTGRES_TLS_UPGRADE_FAILED, - error.UnexpectedMessage => JSC.Error.ERR_POSTGRES_UNEXPECTED_MESSAGE, - error.UNKNOWN_AUTHENTICATION_METHOD => JSC.Error.ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD, - error.UNSUPPORTED_AUTHENTICATION_METHOD => JSC.Error.ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD, - error.UnsupportedByteaFormat => JSC.Error.ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT, - error.UnsupportedIntegerSize => JSC.Error.ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE, - error.JSError => { - this.failWithJSValue(globalObject.takeException(error.JSError)); - return; - }, - error.OutOfMemory => { - // TODO: add binding for creating an out of memory error? - this.failWithJSValue(globalObject.takeException(globalObject.throwOutOfMemory())); - return; - }, - error.ShortRead => { - bun.unreachablePanic("Assertion failed: ShortRead should be handled by the caller in postgres", .{}); - }, - }; - this.failWithJSValue(error_code.fmt(globalObject, "{s}", .{message})); + + this.failWithJSValue(postgresErrorToJS(globalObject, message, err)); } pub fn onClose(this: *PostgresSQLConnection) void { @@ -1463,7 +1541,6 @@ pub const PostgresSQLConnection = struct { .options = Data{ .temporary = this.options }, }; msg.writeInternal(Writer, this.writer()) catch |err| { - this.refAndClose(); this.fail("Failed to write startup message", err); }; } @@ -1565,16 +1642,21 @@ pub const PostgresSQLConnection = struct { pub fn onData(this: *PostgresSQLConnection, data: []const u8) void { this.ref(); + this.flags.is_processing_data = true; const vm = this.globalObject.bunVM(); + + this.disableConnectionTimeout(); defer { - if (this.status == .connected and this.requests.readableLength() == 0 and this.write_buffer.remaining().len == 0) { + if (this.status == .connected and !this.hasQueryRunning() and this.write_buffer.remaining().len == 0) { // Don't keep the process alive when there's nothing to do. this.poll_ref.unref(vm); } else if (this.status == .connected) { // Keep the process alive if there's something to do. this.poll_ref.ref(vm); } + this.flags.is_processing_data = false; + // reset the connection timeout after we're done processing the data this.resetConnectionTimeout(); this.deref(); } @@ -1583,6 +1665,9 @@ pub const PostgresSQLConnection = struct { event_loop.enter(); defer event_loop.exit(); SocketMonitor.read(data); + // reset the head to the last message so remaining reflects the right amount of bytes + this.read_buffer.head = this.last_message_start; + if (this.read_buffer.remaining().len == 0) { var consumed: usize = 0; var offset: usize = 0; @@ -1590,20 +1675,11 @@ pub const PostgresSQLConnection = struct { PostgresRequest.onData(this, protocol.StackReader, reader) catch |err| { if (err == error.ShortRead) { if (comptime bun.Environment.allow_assert) { - // if (@errorReturnTrace()) |trace| { - // debug("Received short read: last_message_start: {d}, head: {d}, len: {d}\n{}", .{ - // offset, - // consumed, - // data.len, - // trace, - // }); - // } else { - debug("Received short read: last_message_start: {d}, head: {d}, len: {d}", .{ + debug("read_buffer: empty and received short read: last_message_start: {d}, head: {d}, len: {d}", .{ offset, consumed, data.len, }); - // } } this.read_buffer.head = 0; @@ -1616,42 +1692,32 @@ pub const PostgresSQLConnection = struct { this.fail("Failed to read data", err); } }; + // no need to reset anything, its already empty return; } - - { - this.read_buffer.head = this.last_message_start; - this.read_buffer.write(bun.default_allocator, data) catch @panic("failed to write to read buffer"); - PostgresRequest.onData(this, Reader, this.bufferedReader()) catch |err| { - if (err != error.ShortRead) { - bun.handleErrorReturnTrace(err, @errorReturnTrace()); - this.fail("Failed to read data", err); - return; - } - - if (comptime bun.Environment.allow_assert) { - // if (@errorReturnTrace()) |trace| { - // debug("Received short read: last_message_start: {d}, head: {d}, len: {d}\n{}", .{ - // this.last_message_start, - // this.read_buffer.head, - // this.read_buffer.byte_list.len, - // trace, - // }); - // } else { - debug("Received short read: last_message_start: {d}, head: {d}, len: {d}", .{ - this.last_message_start, - this.read_buffer.head, - this.read_buffer.byte_list.len, - }); - // } - } - + // read buffer is not empty, so we need to write the data to the buffer and then read it + this.read_buffer.write(bun.default_allocator, data) catch @panic("failed to write to read buffer"); + PostgresRequest.onData(this, Reader, this.bufferedReader()) catch |err| { + if (err != error.ShortRead) { + bun.handleErrorReturnTrace(err, @errorReturnTrace()); + this.fail("Failed to read data", err); return; - }; + } - this.last_message_start = 0; - this.read_buffer.head = 0; - } + if (comptime bun.Environment.allow_assert) { + debug("read_buffer: not empty and received short read: last_message_start: {d}, head: {d}, len: {d}", .{ + this.last_message_start, + this.read_buffer.head, + this.read_buffer.byte_list.len, + }); + } + return; + }; + + debug("clean read_buffer", .{}); + // success, we read everything! let's reset the last message start and the head + this.last_message_start = 0; + this.read_buffer.head = 0; } pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*PostgresSQLConnection { @@ -1660,10 +1726,8 @@ pub const PostgresSQLConnection = struct { } comptime { - if (!JSC.is_bindgen) { - const jscall = JSC.toJSHostFunction(call); - @export(jscall, .{ .name = "PostgresSQLConnection__createInstance" }); - } + const jscall = JSC.toJSHostFunction(call); + @export(&jscall, .{ .name = "PostgresSQLConnection__createInstance" }); } pub fn call(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { @@ -1779,7 +1843,7 @@ pub const PostgresSQLConnection = struct { .password = password, .options = options, .options_buf = options_buf, - .socket = undefined, + .socket = .{ .SocketTCP = .{ .socket = .{ .detached = {} } } }, .requests = PostgresRequest.Queue.init(bun.default_allocator), .statements = PreparedStatementsMap{}, .tls_config = tls_config, @@ -1799,6 +1863,7 @@ pub const PostgresSQLConnection = struct { PostgresSQLConnection.onconnectSetCached(js_value, globalObject, on_connect); PostgresSQLConnection.oncloseSetCached(js_value, globalObject, on_close); + bun.analytics.Features.postgres_connections += 1; { const hostname = hostname_str.toUTF8(bun.default_allocator); @@ -1941,13 +2006,46 @@ pub const PostgresSQLConnection = struct { bun.default_allocator.destroy(this); } - fn refAndClose(this: *@This()) void { + 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 + while (this.current()) |request| { + switch (request.status) { + // pending we will fail the request and the stmt will be marked as error ConnectionClosed too + .pending => { + 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); + } + }, + // in the middle of running + .binding, + .running, + => { + if (js_reason) |reason| { + request.onJSError(reason, this.globalObject); + } else { + request.onError(.{ .postgres_error = AnyPostgresError.ConnectionClosed }, this.globalObject); + } + }, + // just ignore success and fail cases + .success, .fail => {}, + } + request.deref(); + this.requests.discard(1); + } } pub fn disconnect(this: *@This()) void { @@ -1955,7 +2053,7 @@ pub const PostgresSQLConnection = struct { if (this.status == .connected) { this.status = .disconnected; - this.refAndClose(); + this.refAndClose(null); } } @@ -1967,6 +2065,10 @@ pub const PostgresSQLConnection = struct { return this.requests.peekItem(0); } + fn hasQueryRunning(this: *PostgresSQLConnection) bool { + return !this.flags.is_ready_for_query or this.current() != null; + } + pub const Writer = struct { connection: *PostgresSQLConnection, @@ -2309,7 +2411,7 @@ pub const PostgresSQLConnection = struct { fn pg_ntoT(comptime IntSize: usize, i: anytype) std.meta.Int(.unsigned, IntSize) { @setRuntimeSafety(false); const T = @TypeOf(i); - if (@typeInfo(T) == .Array) { + if (@typeInfo(T) == .array) { return pg_ntoT(IntSize, @as(std.meta.Int(.unsigned, IntSize), @bitCast(i))); } @@ -2448,69 +2550,119 @@ pub const PostgresSQLConnection = struct { }; }; - fn advance(this: *PostgresSQLConnection) !bool { - defer this.updateRef(); - var any = false; - + fn advance(this: *PostgresSQLConnection) !void { while (this.requests.readableLength() > 0) { var req: *PostgresSQLQuery = this.requests.peekItem(0); switch (req.status) { .pending => { const stmt = req.statement orelse return error.ExpectedStatement; - if (stmt.status == .failed) { - req.onError(stmt.error_response, this.globalObject); - this.requests.discard(1); - any = true; - } else { - break; - } - }, - .success, .fail => { - this.requests.discard(1); - req.deref(); - any = true; - }, - else => break, - } - } - while (this.requests.readableLength() > 0) { - var req: *PostgresSQLQuery = this.requests.peekItem(0); - const stmt = req.statement orelse return error.ExpectedStatement; - - switch (stmt.status) { - .prepared => { - if (req.status == .pending and stmt.status == .prepared) { - const binding_value = PostgresSQLQuery.bindingGetCached(req.thisValue) orelse .zero; - const columns_value = PostgresSQLQuery.columnsGetCached(req.thisValue) orelse .zero; - PostgresRequest.bindAndExecute(this.globalObject, stmt, binding_value, columns_value, PostgresSQLConnection.Writer, this.writer()) catch |err| { - req.onWriteFail(err, this.globalObject, this.getQueriesArray()); + switch (stmt.status) { + .failed => { + bun.assert(stmt.error_response != null); + req.onError(stmt.error_response.?, this.globalObject); req.deref(); this.requests.discard(1); + continue; - }; - req.status = .binding; - req.flags.binary = stmt.fields.len > 0; - any = true; - } else { - break; + }, + .prepared => { + const thisValue = req.thisValue.get(); + bun.assert(thisValue != .zero); + const binding_value = PostgresSQLQuery.bindingGetCached(thisValue) orelse .zero; + const columns_value = PostgresSQLQuery.columnsGetCached(thisValue) orelse .zero; + req.flags.binary = stmt.fields.len > 0; + + PostgresRequest.bindAndExecute(this.globalObject, stmt, binding_value, columns_value, PostgresSQLConnection.Writer, this.writer()) catch |err| { + req.onWriteFail(err, this.globalObject, this.getQueriesArray()); + req.deref(); + this.requests.discard(1); + + continue; + }; + req.status = .binding; + return; + }, + .pending => { + // statement is pending, lets write/parse it + var query_str = req.query.toUTF8(bun.default_allocator); + defer query_str.deinit(); + 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); + // prepareAndQueryWithSignature will write + bind + execute, it will change to running after binding is complete + const binding_value = PostgresSQLQuery.bindingGetCached(thisValue) orelse .zero; + + PostgresRequest.prepareAndQueryWithSignature(this.globalObject, query_str.slice(), binding_value, PostgresSQLConnection.Writer, this.writer(), &stmt.signature) catch |err| { + stmt.status = .failed; + stmt.error_response = .{ .postgres_error = err }; + req.onWriteFail(err, this.globalObject, this.getQueriesArray()); + req.deref(); + this.requests.discard(1); + + continue; + }; + req.status = .binding; + stmt.status = .parsing; + + return; + } + const connection_writer = this.writer(); + // write query and wait for it to be prepared + PostgresRequest.writeQuery(query_str.slice(), stmt.signature.prepared_statement_name, stmt.signature.fields, PostgresSQLConnection.Writer, connection_writer) catch |err| { + stmt.error_response = .{ .postgres_error = err }; + stmt.status = .failed; + + req.onWriteFail(err, this.globalObject, this.getQueriesArray()); + req.deref(); + this.requests.discard(1); + + continue; + }; + connection_writer.write(&protocol.Sync) catch |err| { + stmt.error_response = .{ .postgres_error = err }; + stmt.status = .failed; + + req.onWriteFail(err, this.globalObject, this.getQueriesArray()); + req.deref(); + this.requests.discard(1); + + continue; + }; + stmt.status = .parsing; + return; + }, + .parsing => { + // we are still parsing, lets wait for it to be prepared or failed + return; + }, } }, - else => break, + + .running, .binding => { + // if we are binding it will switch to running immediately + // if we are running, we need to wait for it to be success or fail + return; + }, + .success, .fail => { + req.deref(); + this.requests.discard(1); + continue; + }, } } - - return any; } pub fn getQueriesArray(this: *const PostgresSQLConnection) JSValue { return PostgresSQLConnection.queriesGetCached(this.js_value) orelse .zero; } - pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.EnumLiteral), comptime Context: type, reader: protocol.NewReader(Context)) AnyPostgresError!void { + pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.enum_literal), comptime Context: type, reader: protocol.NewReader(Context)) AnyPostgresError!void { debug("on({s})", .{@tagName(MessageType)}); if (comptime MessageType != .ReadyForQuery) { - this.is_ready_for_query = false; + this.flags.is_ready_for_query = false; } switch (comptime MessageType) { @@ -2571,13 +2723,14 @@ pub const PostgresSQLConnection = struct { DataCell.Putter.put, ); } - - const pending_value = if (request.thisValue == .zero) .zero else PostgresSQLQuery.pendingValueGetCached(request.thisValue) orelse .zero; + const thisValue = request.thisValue.get(); + bun.assert(thisValue != .zero); + const pending_value = PostgresSQLQuery.pendingValueGetCached(thisValue) orelse .zero; pending_value.ensureStillAlive(); const result = putter.toJS(this.globalObject, pending_value, structure, statement.fields_flags, request.flags.result_mode); if (pending_value == .zero) { - PostgresSQLQuery.pendingValueSetCached(request.thisValue, this.globalObject, result); + PostgresSQLQuery.pendingValueSetCached(thisValue, this.globalObject, result); } }, .CopyData => { @@ -2597,18 +2750,13 @@ pub const PostgresSQLConnection = struct { var ready_for_query: protocol.ReadyForQuery = undefined; try ready_for_query.decodeInternal(Context, reader); - if (this.pending_disconnect) { - this.disconnect(); - return; - } - this.setStatus(.connected); - this.is_ready_for_query = true; + this.flags.is_ready_for_query = true; this.socket.setTimeout(300); - if (try this.advance() or this.is_ready_for_query) { - this.flushData(); - } + try this.advance(); + + this.flushData(); }, .CommandComplete => { var request = this.current() orelse return error.ExpectedRequest; @@ -2619,7 +2767,6 @@ pub const PostgresSQLConnection = struct { cmd.deinit(); } debug("-> {s}", .{cmd.command_tag.slice()}); - _ = this.requests.discard(1); defer this.updateRef(); request.onSuccess(cmd.command_tag.slice(), this.globalObject, this.js_value); }, @@ -2879,29 +3026,26 @@ pub const PostgresSQLConnection = struct { if (request.statement) |stmt| { if (stmt.status == PostgresSQLStatement.Status.parsing) { stmt.status = PostgresSQLStatement.Status.failed; - stmt.error_response = err; + stmt.error_response = .{ .protocol = err }; is_error_owned = false; if (this.statements.remove(bun.hash(stmt.signature.name))) { stmt.deref(); } } } - _ = this.requests.discard(1); this.updateRef(); - request.onError(err, this.globalObject); + request.onError(.{ .protocol = err }, this.globalObject); }, .PortalSuspended => { // try reader.eatMessage(&protocol.PortalSuspended); // var request = this.current() orelse return error.ExpectedRequest; // _ = request; - // _ = this.requests.discard(1); debug("TODO PortalSuspended", .{}); }, .CloseComplete => { try reader.eatMessage(protocol.CloseComplete); var request = this.current() orelse return error.ExpectedRequest; - _ = this.requests.discard(1); request.onSuccess("CLOSECOMPLETE", this.globalObject, this.getQueriesArray()); }, .CopyInResponse => { @@ -2917,7 +3061,6 @@ pub const PostgresSQLConnection = struct { .EmptyQueryResponse => { try reader.eatMessage(protocol.EmptyQueryResponse); var request = this.current() orelse return error.ExpectedRequest; - _ = this.requests.discard(1); this.updateRef(); request.onSuccess("", this.globalObject, this.getQueriesArray()); }, @@ -2971,15 +3114,38 @@ pub const PostgresSQLStatement = struct { fields: []protocol.FieldDescription = &[_]protocol.FieldDescription{}, parameters: []const int4 = &[_]int4{}, signature: Signature, - status: Status = Status.parsing, - error_response: protocol.ErrorResponse = .{}, + status: Status = Status.pending, + error_response: ?Error = null, needs_duplicate_check: bool = true, fields_flags: PostgresSQLConnection.DataCell.Flags = .{}, + pub const Error = union(enum) { + protocol: protocol.ErrorResponse, + postgres_error: AnyPostgresError, + + pub fn deinit(this: *@This()) void { + switch (this.*) { + .protocol => |*err| err.deinit(), + .postgres_error => {}, + } + } + + pub fn toJS(this: *const @This(), globalObject: *JSC.JSGlobalObject) JSValue { + return switch (this.*) { + .protocol => |err| err.toJS(globalObject), + .postgres_error => |err| postgresErrorToJS(globalObject, null, err), + }; + } + }; pub const Status = enum { + pending, parsing, prepared, failed, + + pub fn isRunning(this: @This()) bool { + return this == .parsing; + } }; pub fn ref(this: *@This()) void { bun.assert(this.ref_count > 0); @@ -3051,7 +3217,11 @@ pub const PostgresSQLStatement = struct { bun.default_allocator.free(this.fields); bun.default_allocator.free(this.parameters); this.cached_structure.deinit(); - this.error_response.deinit(); + if (this.error_response) |err| { + this.error_response = null; + var _error = err; + _error.deinit(); + } this.signature.deinit(); bun.default_allocator.destroy(this); } diff --git a/src/sql/postgres/postgres_types.zig b/src/sql/postgres/postgres_types.zig index a6fa23ff73f906..9a62d07bf18223 100644 --- a/src/sql/postgres/postgres_types.zig +++ b/src/sql/postgres/postgres_types.zig @@ -177,7 +177,7 @@ pub const Tag = enum(short) { jsonpath_array = 4073, _, - pub fn name(this: Tag) ?[]const u8 { + pub fn tagName(this: Tag) ?[]const u8 { return std.enums.tagName(Tag, this); } @@ -345,7 +345,7 @@ pub const Tag = enum(short) { return .timestamptz; } - if (tag.isTypedArray()) { + if (tag.isTypedArrayOrArrayBuffer()) { if (tag == .Int32Array) return .int4_array; diff --git a/src/string.zig b/src/string.zig index 5b0c534a1656d6..411be37d49fe35 100644 --- a/src/string.zig +++ b/src/string.zig @@ -384,6 +384,7 @@ pub const String = extern struct { fn createUninitializedLatin1(len: usize) struct { String, []u8 } { bun.assert(len > 0); const string = BunString__fromLatin1Unitialized(len); + _ = validateRefCount(string); const wtf = string.value.WTFStringImpl; return .{ string, @@ -394,6 +395,7 @@ pub const String = extern struct { fn createUninitializedUTF16(len: usize) struct { String, []u16 } { bun.assert(len > 0); const string = BunString__fromUTF16Unitialized(len); + _ = validateRefCount(string); const wtf = string.value.WTFStringImpl; return .{ string, @@ -434,21 +436,31 @@ pub const String = extern struct { pub fn createLatin1(bytes: []const u8) String { JSC.markBinding(@src()); if (bytes.len == 0) return String.empty; - return BunString__fromLatin1(bytes.ptr, bytes.len); + return validateRefCount(BunString__fromLatin1(bytes.ptr, bytes.len)); + } + + pub inline fn validateRefCount(this: String) String { + if (comptime bun.Environment.isDebug) { + // Newly created strings should have a ref count of 1 + if (!this.isEmpty()) { + const ref_count = this.value.WTFStringImpl.refCount(); + bun.assert(ref_count == 1); + } + } + + return this; } pub fn createUTF8(bytes: []const u8) String { - JSC.markBinding(@src()); - if (bytes.len == 0) return String.empty; - return BunString__fromBytes(bytes.ptr, bytes.len); + return JSC.WebCore.Encoder.toBunStringComptime(bytes, .utf8); } pub fn createUTF16(bytes: []const u16) String { if (bytes.len == 0) return String.empty; if (bun.strings.firstNonASCII16([]const u16, bytes) == null) { - return BunString__fromUTF16ToLatin1(bytes.ptr, bytes.len); + return validateRefCount(BunString__fromUTF16ToLatin1(bytes.ptr, bytes.len)); } - return BunString__fromUTF16(bytes.ptr, bytes.len); + return validateRefCount(BunString__fromUTF16(bytes.ptr, bytes.len)); } pub fn createFormat(comptime fmt: [:0]const u8, args: anytype) OOM!String { @@ -580,10 +592,10 @@ pub const String = extern struct { const info = @typeInfo(Type); // Zig string literals - if (info == .Pointer and info.Pointer.size == .One and info.Pointer.is_const) { - const child_info = @typeInfo(info.Pointer.child); - if (child_info == .Array and child_info.Array.child == u8) { - if (child_info.Array.len == 0) return String.empty; + if (info == .pointer and info.pointer.size == .one and info.pointer.is_const) { + const child_info = @typeInfo(info.pointer.child); + if (child_info == .array and child_info.array.child == u8) { + if (child_info.array.len == 0) return String.empty; return static(value); } } @@ -642,7 +654,7 @@ pub const String = extern struct { } return dead; } - return BunString__createExternal(bytes.ptr, bytes.len, isLatin1, ctx, callback); + return validateRefCount(BunString__createExternal(bytes.ptr, bytes.len, isLatin1, ctx, callback)); } /// This should rarely be used. The WTF::StringImpl* will never be freed. @@ -682,8 +694,8 @@ pub const String = extern struct { } return switch (comptime kind) { - .latin1 => BunString__createExternalGloballyAllocatedLatin1(bytes.ptr, bytes.len), - .utf16 => BunString__createExternalGloballyAllocatedUTF16(bytes.ptr, bytes.len), + .latin1 => validateRefCount(BunString__createExternalGloballyAllocatedLatin1(bytes.ptr, bytes.len)), + .utf16 => validateRefCount(BunString__createExternalGloballyAllocatedUTF16(bytes.ptr, bytes.len)), }; } diff --git a/src/string_immutable.zig b/src/string_immutable.zig index 75fe6b14417b69..365d1acda0bc56 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -1091,7 +1091,7 @@ fn eqlComptimeCheckLenWithKnownType(comptime Type: type, a: []const Type, compti /// strings.eqlComptime(input, "hello world"); /// strings.eqlComptime(input, "hai"); pub fn eqlComptimeCheckLenWithType(comptime Type: type, a: []const Type, comptime b: anytype, comptime check_len: bool) bool { - return eqlComptimeCheckLenWithKnownType(comptime Type, a, if (@typeInfo(@TypeOf(b)) != .Pointer) &b else b, comptime check_len); + return eqlComptimeCheckLenWithKnownType(comptime Type, a, if (@typeInfo(@TypeOf(b)) != .pointer) &b else b, comptime check_len); } pub fn eqlCaseInsensitiveASCIIIgnoreLength( @@ -2311,9 +2311,6 @@ pub fn toUTF8AppendToList(list: *std.ArrayList(u8), utf16: []const u16) !void { } pub fn toUTF8FromLatin1(allocator: std.mem.Allocator, latin1: []const u8) !?std.ArrayList(u8) { - if (bun.JSC.is_bindgen) - unreachable; - if (isAllASCII(latin1)) return null; @@ -2322,9 +2319,6 @@ pub fn toUTF8FromLatin1(allocator: std.mem.Allocator, latin1: []const u8) !?std. } pub fn toUTF8FromLatin1Z(allocator: std.mem.Allocator, latin1: []const u8) !?std.ArrayList(u8) { - if (bun.JSC.is_bindgen) - unreachable; - if (isAllASCII(latin1)) return null; @@ -2404,7 +2398,7 @@ pub fn allocateLatin1IntoUTF8(allocator: std.mem.Allocator, comptime Type: type, return try foo.toOwnedSlice(); } -pub fn allocateLatin1IntoUTF8WithList(list_: std.ArrayList(u8), offset_into_list: usize, comptime Type: type, latin1_: Type) !std.ArrayList(u8) { +pub fn allocateLatin1IntoUTF8WithList(list_: std.ArrayList(u8), offset_into_list: usize, comptime Type: type, latin1_: Type) OOM!std.ArrayList(u8) { var latin1 = latin1_; var i: usize = offset_into_list; var list = list_; @@ -4648,11 +4642,10 @@ pub fn trimLeadingChar(slice: []const u8, char: u8) []const u8 { /// e.g. /// `trimLeadingPattern2("abcdef", 'a', 'b') == "cdef"` pub fn trimLeadingPattern2(slice_: []const u8, comptime byte1: u8, comptime byte2: u8) []const u8 { - const pattern: u16 = comptime @as(u16, byte2) << 8 | @as(u16, byte1); + // const pattern: u16 = comptime @as(u16, byte2) << 8 | @as(u16, byte1); var slice = slice_; while (slice.len >= 2) { - const sliceu16: [*]const u16 = @ptrCast(@alignCast(slice.ptr)); - if (sliceu16[0] == pattern) { + if (slice[0] == byte1 and slice[1] == byte2) { slice = slice[2..]; } else { break; @@ -4769,6 +4762,7 @@ pub fn indexOfLineRanges(text: []const u8, target_line: u32, comptime line_range else => continue, } } + @panic("unreachable"); }; if (ranges.len == line_range_count and current_line <= target_line) { @@ -5560,7 +5554,7 @@ pub fn cloneNormalizingSeparators( ) ![]u8 { // remove duplicate slashes in the file path const base = withoutTrailingSlash(input); - var tokenized = std.mem.tokenize(u8, base, std.fs.path.sep_str); + var tokenized = std.mem.tokenizeScalar(u8, base, std.fs.path.sep); var buf = try allocator.alloc(u8, base.len + 2); if (comptime Environment.allow_assert) assert(base.len > 0); if (base[0] == std.fs.path.sep) { diff --git a/src/sync.zig b/src/sync.zig index b71040f6fab026..e147116ec6485c 100644 --- a/src/sync.zig +++ b/src/sync.zig @@ -634,7 +634,7 @@ pub const RwLock = if (@import("builtin").os.tag != .windows and @import("builti writer_count: i32 = 0, waiters: [2]?*anyopaque = [_]?*anyopaque{ null, null }, }, - .kfreebsd, .freebsd, .openbsd => extern struct { + .freebsd, .openbsd => extern struct { ptr: ?*anyopaque = null, }, .hermit => extern struct { @@ -946,7 +946,7 @@ else if (@import("builtin").os.tag == .linux) } fn lockSlow(self: *Mutex, current_state: State) void { - @setCold(true); + @branchHint(.cold); var new_state = current_state; while (true) { @@ -992,7 +992,7 @@ else if (@import("builtin").os.tag == .linux) } fn unlockSlow(self: *Mutex) void { - @setCold(true); + @branchHint(.cold); Futex.wake(@as(*const i32, @ptrCast(&self.state))); } diff --git a/src/sys.zig b/src/sys.zig index 05a8f4370a0809..b90fbbbe2095c7 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -65,11 +65,11 @@ pub const O = switch (Environment.os) { pub const NOFOLLOW = 0x0100; pub const SYMLINK = 0x200000; pub const EVTONLY = 0x8000; - pub const CLOEXEC = 0x1000000; + pub const CLOEXEC = 0x01000000; pub const ACCMODE = 3; pub const ALERT = 536870912; pub const ASYNC = 64; - pub const DIRECTORY = 1048576; + pub const DIRECTORY = 0x00100000; pub const DP_GETRAWENCRYPTED = 1; pub const DP_GETRAWUNENCRYPTED = 2; pub const DSYNC = 4194304; @@ -456,6 +456,7 @@ pub const Error = struct { /// 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)), @@ -878,7 +879,7 @@ pub fn fstatat(fd: bun.FileDescriptor, path: [:0]const u8) Maybe(bun.Stat) { return Maybe(bun.Stat){ .result = stat_buf }; } -pub fn mkdir(file_path: [:0]const u8, flags: bun.Mode) Maybe(void) { +pub fn mkdir(file_path: [:0]const u8, flags: mode_t) Maybe(void) { return switch (Environment.os) { .mac => Maybe(void).errnoSysP(syscall.mkdir(file_path, flags), .mkdir, file_path) orelse Maybe(void).success, @@ -888,7 +889,7 @@ pub fn mkdir(file_path: [:0]const u8, flags: bun.Mode) Maybe(void) { const wbuf = bun.WPathBufferPool.get(); defer bun.WPathBufferPool.put(wbuf); return Maybe(void).errnoSysP( - kernel32.CreateDirectoryW(bun.strings.toKernel32Path(wbuf, file_path).ptr, null), + bun.windows.CreateDirectoryW(bun.strings.toKernel32Path(wbuf, file_path).ptr, null), .mkdir, file_path, ) orelse Maybe(void).success; @@ -898,7 +899,7 @@ pub fn mkdir(file_path: [:0]const u8, flags: bun.Mode) Maybe(void) { }; } -pub fn mkdirA(file_path: []const u8, flags: bun.Mode) Maybe(void) { +pub fn mkdirA(file_path: []const u8, flags: mode_t) Maybe(void) { if (comptime Environment.isMac) { return Maybe(void).errnoSysP(syscall.mkdir(&(std.posix.toPosixPath(file_path) catch return Maybe(void){ .err = .{ @@ -930,7 +931,7 @@ pub fn mkdirA(file_path: []const u8, flags: bun.Mode) Maybe(void) { } } -pub fn mkdirOSPath(file_path: bun.OSPathSliceZ, flags: bun.Mode) Maybe(void) { +pub fn mkdirOSPath(file_path: bun.OSPathSliceZ, flags: mode_t) Maybe(void) { return switch (Environment.os) { else => mkdir(file_path, flags), .windows => { @@ -951,9 +952,14 @@ pub fn mkdirOSPath(file_path: bun.OSPathSliceZ, flags: bun.Mode) Maybe(void) { } const fnctl_int = if (Environment.isLinux) usize else c_int; -pub fn fcntl(fd: bun.FileDescriptor, cmd: i32, arg: fnctl_int) Maybe(fnctl_int) { +pub fn fcntl(fd: bun.FileDescriptor, cmd: i32, arg: anytype) Maybe(fnctl_int) { while (true) { - const result = fcntl_symbol(fd.cast(), cmd, arg); + const result = switch (@TypeOf(arg)) { + i32, comptime_int, c_int => fcntl_symbol(fd.cast(), cmd, @as(c_int, arg)), + i64 => fcntl_symbol(fd.cast(), cmd, @as(c_long, @bitCast(arg))), + *const anyopaque, *anyopaque, usize => fcntl_symbol(fd.cast(), cmd, arg), + else => @compileError("Unsupported argument type for fcntl"), + }; if (Maybe(fnctl_int).errnoSysFd(result, .fcntl, fd)) |err| { if (err.getErrno() == .INTR) continue; return err; @@ -1567,11 +1573,11 @@ pub noinline fn openFileAtWindowsA( return openFileAtWindowsT(u8, dirFd, path, opts); } -pub fn openatWindowsT(comptime T: type, dir: bun.FileDescriptor, path: []const T, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn openatWindowsT(comptime T: type, dir: bun.FileDescriptor, path: []const T, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { return openatWindowsTMaybeNormalize(T, dir, path, flags, perm, true); } -fn openatWindowsTMaybeNormalize(comptime T: type, dir: bun.FileDescriptor, path: []const T, flags: bun.Mode, perm: bun.Mode, comptime normalize: bool) Maybe(bun.FileDescriptor) { +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, @@ -1647,7 +1653,7 @@ fn openatWindowsTMaybeNormalize(comptime T: type, dir: bun.FileDescriptor, path: pub fn openatWindows( dir: anytype, path: []const u16, - flags: bun.Mode, + flags: i32, perm: bun.Mode, ) Maybe(bun.FileDescriptor) { return openatWindowsT(u16, bun.toFD(dir), path, flags, perm); @@ -1656,18 +1662,18 @@ pub fn openatWindows( pub fn openatWindowsA( dir: bun.FileDescriptor, path: []const u8, - flags: bun.Mode, + flags: i32, perm: bun.Mode, ) Maybe(bun.FileDescriptor) { return openatWindowsT(u8, dir, path, flags, perm); } -pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSliceZ, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSliceZ, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { if (comptime Environment.isMac) { // https://opensource.apple.com/source/xnu/xnu-7195.81.3/libsyscall/wrappers/open-base.c const rc = syscall.@"openat$NOCANCEL"(dirfd.cast(), file_path.ptr, @as(c_uint, @intCast(flags)), @as(c_int, @intCast(perm))); if (comptime Environment.allow_assert) - log("openat({}, {s}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), rc }); + log("openat({}, {s}, {d}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), flags, rc }); return Maybe(bun.FileDescriptor).errnoSysFP(rc, .open, dirfd, file_path) orelse .{ .result = bun.toFD(rc) }; } else if (comptime Environment.isWindows) { @@ -1677,7 +1683,8 @@ pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSliceZ, flag while (true) { const rc = syscall.openat(dirfd.cast(), file_path, bun.O.toPacked(flags), perm); if (comptime Environment.allow_assert) - log("openat({}, {s}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), rc }); + log("openat({}, {s}, {d}) = {d}", .{ dirfd, bun.sliceTo(file_path, 0), flags, rc }); + return switch (Syscall.getErrno(rc)) { .SUCCESS => .{ .result = bun.toFD(@as(i32, @intCast(rc))) }, .INTR => continue, @@ -1693,7 +1700,7 @@ pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSliceZ, flag } } -pub fn access(path: bun.OSPathSliceZ, mode: bun.Mode) Maybe(void) { +pub fn access(path: bun.OSPathSliceZ, mode: i32) Maybe(void) { if (Environment.isWindows) { const attrs = getFileAttributes(path) orelse { return .{ .err = .{ @@ -1717,7 +1724,7 @@ pub fn access(path: bun.OSPathSliceZ, mode: bun.Mode) Maybe(void) { return Maybe(void).errnoSysP(syscall.access(path, mode), .access, path) orelse .{ .result = {} }; } -pub fn openat(dirfd: bun.FileDescriptor, file_path: [:0]const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn openat(dirfd: bun.FileDescriptor, file_path: [:0]const u8, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { if (comptime Environment.isWindows) { return openatWindowsT(u8, dirfd, file_path, flags, perm); } else { @@ -1739,7 +1746,7 @@ pub fn openatFileWithLibuvFlags(dirfd: bun.FileDescriptor, file_path: [:0]const } } -pub fn openatA(dirfd: bun.FileDescriptor, file_path: []const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn openatA(dirfd: bun.FileDescriptor, file_path: []const u8, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { if (comptime Environment.isWindows) { return openatWindowsT(u8, dirfd, file_path, flags, perm); } @@ -1759,12 +1766,12 @@ pub fn openatA(dirfd: bun.FileDescriptor, file_path: []const u8, flags: bun.Mode ); } -pub fn openA(file_path: []const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn openA(file_path: []const u8, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { // this is what open() does anyway. return openatA(bun.toFD((std.fs.cwd().fd)), file_path, flags, perm); } -pub fn open(file_path: [:0]const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn open(file_path: [:0]const u8, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { // TODO(@paperclover): this should not use libuv; when the libuv path is // removed here, the call sites in node_fs.zig should make sure they parse // the libuv specific file flags using the WindowsOpenFlags structure. @@ -2129,7 +2136,7 @@ pub fn read(fd: bun.FileDescriptor, buf: []u8) Maybe(usize) { var amount_read: u32 = 0; const rc = kernel32.ReadFile(fd.cast(), buf.ptr, @as(u32, @intCast(adjusted_len)), &amount_read, null); if (rc == windows.FALSE) { - const ret = .{ + const ret: Maybe(usize) = .{ .err = Syscall.Error{ .errno = @intFromEnum(bun.windows.getLastErrno()), .syscall = .read, @@ -2528,7 +2535,7 @@ pub fn symlinkW(dest: [:0]const u16, target: [:0]const u16, options: WindowsSyml while (true) { const flags = options.flags(); - if (windows.kernel32.CreateSymbolicLinkW(dest, target, flags) == 0) { + if (windows.CreateSymbolicLinkW(dest, target, flags) == 0) { const errno = bun.windows.Win32Error.get(); log("CreateSymbolicLinkW({}, {}, {any}) = {s}", .{ bun.fmt.fmtPath(u16, dest, .{}), @@ -2581,7 +2588,7 @@ pub fn clonefile(from: [:0]const u8, to: [:0]const u8) Maybe(void) { } } -pub fn copyfile(from: [:0]const u8, to: [:0]const u8, flags: c_int) Maybe(void) { +pub fn copyfile(from: [:0]const u8, to: [:0]const u8, flags: posix.system.COPYFILE) Maybe(void) { if (comptime !Environment.isMac) @compileError("macOS only"); while (true) { @@ -2593,7 +2600,7 @@ pub fn copyfile(from: [:0]const u8, to: [:0]const u8, flags: c_int) Maybe(void) } } -pub fn fcopyfile(fd_in: bun.FileDescriptor, fd_out: bun.FileDescriptor, flags: u32) Maybe(void) { +pub fn fcopyfile(fd_in: bun.FileDescriptor, fd_out: bun.FileDescriptor, flags: posix.system.COPYFILE) Maybe(void) { if (comptime !Environment.isMac) @compileError("macOS only"); while (true) { @@ -2695,8 +2702,9 @@ pub fn getFdPath(fd: bun.FileDescriptor, out_buffer: *[MAX_PATH_BYTES]u8) Maybe( // On macOS, we can use F.GETPATH fcntl command to query the OS for // the path to the file descriptor. @memset(out_buffer[0..MAX_PATH_BYTES], 0); - if (Maybe([]u8).errnoSys(syscall.fcntl(fd.cast(), posix.F.GETPATH, out_buffer), .fcntl)) |err| { - return err; + switch (fcntl(fd, posix.F.GETPATH, @intFromPtr(out_buffer))) { + .err => |err| return .{ .err = err }, + .result => {}, } const len = mem.indexOfScalar(u8, out_buffer[0..], @as(u8, 0)) orelse MAX_PATH_BYTES; return .{ .result = out_buffer[0..len] }; @@ -2933,13 +2941,17 @@ pub fn setPipeCapacityOnLinux(fd: bun.FileDescriptor, capacity: usize) Maybe(usi // We don't use glibc here // It didn't work. Always returned 0. - const pipe_len = std.os.linux.fcntl(fd.cast(), F_GETPIPE_SZ, 0); - if (Maybe(usize).errnoSysFd(pipe_len, .fcntl, fd)) |err| return err; + const pipe_len = switch (fcntl(fd, F_GETPIPE_SZ, 0)) { + .result => |result| result, + .err => |err| return err, + }; if (pipe_len == 0) return Maybe(usize){ .result = 0 }; if (pipe_len >= capacity) return Maybe(usize){ .result = pipe_len }; - const new_pipe_len = std.os.linux.fcntl(fd.cast(), F_SETPIPE_SZ, capacity); - if (Maybe(usize).errnoSysFd(new_pipe_len, .fcntl, fd)) |err| return err; + const new_pipe_len = switch (fcntl(fd, F_SETPIPE_SZ, capacity)) { + .result => |result| result, + .err => |err| return err, + }; return Maybe(usize){ .result = new_pipe_len }; } @@ -3086,7 +3098,7 @@ pub fn existsOSPath(path: bun.OSPathSliceZ, file_only: bool) bool { null, ); if (rc == w.INVALID_HANDLE_VALUE) return false; - defer _ = std.os.windows.kernel32.CloseHandle(rc); + defer _ = bun.windows.CloseHandle(rc); return true; } return true; @@ -3232,11 +3244,11 @@ pub fn futimens(fd: bun.FileDescriptor, atime: JSC.Node.TimeLike, mtime: JSC.Nod while (true) { const rc = syscall.futimens(fd.cast(), &[2]syscall.timespec{ - .{ .tv_sec = @intCast(atime.tv_sec), .tv_nsec = atime.tv_nsec }, - .{ .tv_sec = @intCast(mtime.tv_sec), .tv_nsec = mtime.tv_nsec }, + .{ .sec = @intCast(atime.sec), .nsec = atime.nsec }, + .{ .sec = @intCast(mtime.sec), .nsec = mtime.nsec }, }); - log("futimens({}, accessed=({d}, {d}), modified=({d}, {d})) = {d}", .{ fd, atime.tv_sec, atime.tv_nsec, mtime.tv_sec, mtime.tv_nsec, rc }); + log("futimens({}, accessed=({d}, {d}), modified=({d}, {d})) = {d}", .{ fd, atime.sec, atime.nsec, mtime.sec, mtime.nsec, rc }); if (rc == 0) { return Maybe(void).success; @@ -3256,8 +3268,8 @@ fn utimensWithFlags(path: bun.OSPathSliceZ, atime: JSC.Node.TimeLike, mtime: JSC while (true) { var times: [2]syscall.timespec = .{ - .{ .tv_sec = @intCast(atime.tv_sec), .tv_nsec = atime.tv_nsec }, - .{ .tv_sec = @intCast(mtime.tv_sec), .tv_nsec = mtime.tv_nsec }, + .{ .sec = @intCast(atime.sec), .nsec = atime.nsec }, + .{ .sec = @intCast(mtime.sec), .nsec = mtime.nsec }, }; const rc = syscall.utimensat( std.fs.cwd().fd, @@ -3267,7 +3279,7 @@ fn utimensWithFlags(path: bun.OSPathSliceZ, atime: JSC.Node.TimeLike, mtime: JSC flags, ); - log("utimensat({d}, atime=({d}, {d}), mtime=({d}, {d})) = {d}", .{ std.fs.cwd().fd, atime.tv_sec, atime.tv_nsec, mtime.tv_sec, mtime.tv_nsec, rc }); + log("utimensat({d}, atime=({d}, {d}), mtime=({d}, {d})) = {d}", .{ std.fs.cwd().fd, atime.sec, atime.nsec, mtime.sec, mtime.nsec, rc }); if (rc == 0) { return Maybe(void).success; @@ -3282,25 +3294,38 @@ fn utimensWithFlags(path: bun.OSPathSliceZ, atime: JSC.Node.TimeLike, mtime: JSC unreachable; } +pub fn getFcntlFlags(fd: bun.FileDescriptor) Maybe(fnctl_int) { + return switch (bun.sys.fcntl( + fd, + std.posix.F.GETFL, + 0, + )) { + .result => |f| .{ .result = f }, + .err => |err| .{ .err = err }, + }; +} + pub fn utimens(path: bun.OSPathSliceZ, atime: JSC.Node.TimeLike, mtime: JSC.Node.TimeLike) Maybe(void) { return utimensWithFlags(path, atime, mtime, 0); } pub fn setNonblocking(fd: bun.FileDescriptor) Maybe(void) { - const flags = switch (bun.sys.fcntl( - fd, - std.posix.F.GETFL, - 0, - )) { - .result => |f| f, + return updateNonblocking(fd, true); +} + +pub fn updateNonblocking(fd: bun.FileDescriptor, nonblocking: bool) Maybe(void) { + const current_flags: i32 = switch (getFcntlFlags(fd)) { + .result => |f| @intCast(f), .err => |err| return .{ .err = err }, }; - const new_flags = flags | bun.O.NONBLOCK; + const new_flags: i32 = if (nonblocking) current_flags | @as(i32, bun.O.NONBLOCK) else current_flags & ~@as(i32, bun.O.NONBLOCK); - switch (bun.sys.fcntl(fd, std.posix.F.SETFL, new_flags)) { - .err => |err| return .{ .err = err }, - .result => {}, + if (new_flags != current_flags) { + switch (bun.sys.fcntl(fd, std.posix.F.SETFL, @as(fnctl_int, @intCast(new_flags)))) { + .err => |err| return .{ .err = err }, + .result => {}, + } } return Maybe(void).success; @@ -3354,7 +3379,7 @@ pub fn existsAt(fd: bun.FileDescriptor, subpath: [:0]const u8) bool { @compileError("TODO: existsAtOSPath"); } -pub extern "C" fn is_executable_file(path: [*:0]const u8) bool; +pub extern "c" fn is_executable_file(path: [*:0]const u8) bool; pub fn isExecutableFileOSPath(path: bun.OSPathSliceZ) bool { if (comptime Environment.isPosix) { @@ -3485,7 +3510,7 @@ pub fn openNullDevice() Maybe(bun.FileDescriptor) { return open("/dev/null", bun.O.RDWR, 0); } -pub fn dupWithFlags(fd: bun.FileDescriptor, flags: i32) Maybe(bun.FileDescriptor) { +pub fn dupWithFlags(fd: bun.FileDescriptor, _: i32) Maybe(bun.FileDescriptor) { if (comptime Environment.isWindows) { var target: windows.HANDLE = undefined; const process = kernel32.GetCurrentProcess(); @@ -3509,16 +3534,10 @@ pub fn dupWithFlags(fd: bun.FileDescriptor, flags: i32) Maybe(bun.FileDescriptor } const ArgType = if (comptime Environment.isLinux) usize else c_int; - const out = syscall.fcntl(fd.cast(), @as(i32, bun.C.F.DUPFD_CLOEXEC), @as(ArgType, 0)); - log("dup({d}) = {d}", .{ fd.cast(), out }); - if (Maybe(bun.FileDescriptor).errnoSysFd(out, .dup, fd)) |err| { - return err; - } - - if (flags != 0) { - const fd_flags: ArgType = @intCast(syscall.fcntl(@intCast(out), @as(i32, std.posix.F.GETFD), @as(ArgType, 0))); - _ = syscall.fcntl(@intCast(out), @as(i32, std.posix.F.SETFD), @as(ArgType, @intCast(fd_flags | @as(ArgType, @intCast(flags))))); - } + const out = switch (fcntl(fd, @as(i32, bun.C.F.DUPFD_CLOEXEC), @as(ArgType, 0))) { + .result => |result| result, + .err => |err| return .{ .err = err }, + }; return Maybe(bun.FileDescriptor){ .result = bun.toFD(@as(u32, @intCast(out))), @@ -3734,18 +3753,18 @@ pub const File = struct { // "handle" matches std.fs.File handle: bun.FileDescriptor, - pub fn openat(other: anytype, path: [:0]const u8, flags: bun.Mode, mode: bun.Mode) Maybe(File) { + pub fn openat(other: anytype, path: [:0]const u8, flags: i32, mode: bun.Mode) Maybe(File) { return switch (This.openat(bun.toFD(other), path, flags, mode)) { .result => |fd| .{ .result = .{ .handle = fd } }, .err => |err| .{ .err = err }, }; } - pub fn open(path: [:0]const u8, flags: bun.Mode, mode: bun.Mode) Maybe(File) { + 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 openatOSPath(other: anytype, path: bun.OSPathSliceZ, flags: bun.Mode, mode: bun.Mode) Maybe(File) { + pub fn openatOSPath(other: anytype, path: bun.OSPathSliceZ, flags: i32, mode: bun.Mode) Maybe(File) { return switch (This.openatOSPath(bun.toFD(other), path, flags, mode)) { .result => |fd| .{ .result = .{ .handle = fd } }, .err => |err| .{ .err = err }, diff --git a/src/sys_uv.zig b/src/sys_uv.zig index 9fc18d100f3bfa..9a574bd581bcd3 100644 --- a/src/sys_uv.zig +++ b/src/sys_uv.zig @@ -38,7 +38,7 @@ pub const access = bun.sys.access; // Note: `req = undefined; req.deinit()` has a saftey-check in a debug build -pub fn open(file_path: [:0]const u8, c_flags: bun.Mode, _perm: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn open(file_path: [:0]const u8, c_flags: i32, _perm: bun.Mode) Maybe(bun.FileDescriptor) { assertIsValidWindowsPath(u8, file_path); var req: uv.fs_t = uv.fs_t.uninitialized; diff --git a/src/tagged_pointer.zig b/src/tagged_pointer.zig index f81aa656b3a111..cb0d798feb533d 100644 --- a/src/tagged_pointer.zig +++ b/src/tagged_pointer.zig @@ -7,7 +7,6 @@ const Environment = bun.Environment; const strings = bun.strings; const default_allocator = bun.default_allocator; const C = bun.C; -const typeBaseName = @import("./meta.zig").typeBaseName; const TagSize = u15; const AddressableSize = u49; @@ -24,7 +23,7 @@ pub const TaggedPointer = packed struct { return .{ ._ptr = 0, .data = data }; } - if (comptime @typeInfo(Ptr) != .Pointer and Ptr != ?*anyopaque) { + if (comptime @typeInfo(Ptr) != .pointer and Ptr != ?*anyopaque) { @compileError(@typeName(Ptr) ++ " must be a ptr, received: " ++ @tagName(@typeInfo(Ptr))); } @@ -74,7 +73,7 @@ pub fn TagTypeEnumWithTypeMap(comptime Types: anytype) struct { @memset(&typeMap, TypeMapT{ .value = 0, .ty = void, .name = "" }); inline for (Types, 0..) |field, i| { - const name = comptime typeBaseName(@typeName(field)); + const name = comptime @typeName(field); enumFields[i] = .{ .name = name, .value = 1024 - i, @@ -84,7 +83,7 @@ pub fn TagTypeEnumWithTypeMap(comptime Types: anytype) struct { return .{ .tag_type = @Type(.{ - .Enum = .{ + .@"enum" = .{ .tag_type = TagSize, .fields = &enumFields, .decls = &.{}, @@ -106,7 +105,7 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type { pub const type_map: TypeMap(Types) = result.ty_map; repr: TaggedPointer, - pub const Null = .{ .repr = .{ ._ptr = 0, .data = 0 } }; + pub const Null: @This() = .{ .repr = .{ ._ptr = 0, .data = 0 } }; pub fn clear(this: *@This()) void { this.* = Null; @@ -132,7 +131,7 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type { const This = @This(); pub fn assert_type(comptime Type: type) void { - const name = comptime typeBaseName(@typeName(Type)); + const name = comptime @typeName(Type); if (!comptime @hasField(Tag, name)) { @compileError("TaggedPointerUnion does not have " ++ name ++ "."); } @@ -163,7 +162,7 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type { pub inline fn is(this: This, comptime Type: type) bool { comptime assert_type(Type); - return this.repr.data == comptime @intFromEnum(@field(Tag, typeBaseName(@typeName(Type)))); + return this.repr.data == comptime @intFromEnum(@field(Tag, @typeName(Type))); } pub fn set(this: *@This(), _ptr: anytype) void { @@ -177,9 +176,9 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type { pub inline fn isValid(this: This) bool { return switch (this.repr.data) { @intFromEnum( - @field(Tag, typeBaseName(@typeName(Types[Types.len - 1]))), + @field(Tag, @typeName(Types[Types.len - 1])), )...@intFromEnum( - @field(Tag, typeBaseName(@typeName(Types[0]))), + @field(Tag, @typeName(Types[0])), ) => true, else => false, }; @@ -200,7 +199,7 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type { pub inline fn init(_ptr: anytype) @This() { const tyinfo = @typeInfo(@TypeOf(_ptr)); - if (tyinfo != .Pointer) @compileError("Only pass pointers to TaggedPointerUnion.init(), you gave us a: " ++ @typeName(@TypeOf(_ptr))); + if (tyinfo != .pointer) @compileError("Only pass pointers to TaggedPointerUnion.init(), you gave us a: " ++ @typeName(@TypeOf(_ptr))); const Type = std.meta.Child(@TypeOf(_ptr)); return initWithType(Type, _ptr); @@ -208,8 +207,8 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type { pub inline fn initWithType(comptime Type: type, _ptr: anytype) @This() { const tyinfo = @typeInfo(@TypeOf(_ptr)); - if (tyinfo != .Pointer) @compileError("Only pass pointers to TaggedPointerUnion.init(), you gave us a: " ++ @typeName(@TypeOf(_ptr))); - const name = comptime typeBaseName(@typeName(Type)); + if (tyinfo != .pointer) @compileError("Only pass pointers to TaggedPointerUnion.init(), you gave us a: " ++ @typeName(@TypeOf(_ptr))); + const name = comptime @typeName(Type); // there will be a compiler error if the passed in type doesn't exist in the enum return This{ .repr = TaggedPointer.init(_ptr, @intFromEnum(@field(Tag, name))) }; diff --git a/src/thread_pool.zig b/src/thread_pool.zig index 457aeb85e1f0f3..1380d2945203ee 100644 --- a/src/thread_pool.zig +++ b/src/thread_pool.zig @@ -768,7 +768,6 @@ const Event = struct { // Acquire barrier to ensure operations before the shutdown() are seen after the wait(). // Shutdown is rare so it's better to have an Acquire barrier here instead of on CAS failure + load which are common. if (state == SHUTDOWN) { - @fence(.acquire); return; } diff --git a/src/toml/toml_lexer.zig b/src/toml/toml_lexer.zig index 5984f33d26cfc4..6467efd7c342fe 100644 --- a/src/toml/toml_lexer.zig +++ b/src/toml/toml_lexer.zig @@ -77,7 +77,7 @@ pub const Lexer = struct { } pub fn syntaxError(self: *Lexer) !void { - @setCold(true); + @branchHint(.cold); // Only add this if there is not already an error. // It is possible that there is a more descriptive error already emitted. @@ -88,7 +88,7 @@ pub const Lexer = struct { } pub fn addError(self: *Lexer, _loc: usize, comptime format: []const u8, args: anytype) void { - @setCold(true); + @branchHint(.cold); var __loc = logger.usize2Loc(_loc); if (__loc.eql(self.prev_error_loc)) { @@ -109,20 +109,20 @@ pub const Lexer = struct { } pub fn addDefaultError(self: *Lexer, msg: []const u8) !void { - @setCold(true); + @branchHint(.cold); self.addError(self.start, "{s}", .{msg}); return Error.SyntaxError; } pub fn addSyntaxError(self: *Lexer, _loc: usize, comptime fmt: []const u8, args: anytype) !void { - @setCold(true); + @branchHint(.cold); self.addError(_loc, fmt, args); return Error.SyntaxError; } pub fn addRangeError(self: *Lexer, r: logger.Range, comptime format: []const u8, args: anytype) !void { - @setCold(true); + @branchHint(.cold); if (self.prev_error_loc.eql(r.loc)) { return; diff --git a/src/toml/toml_parser.zig b/src/toml/toml_parser.zig index 0d07d49714394f..3d5a69e097748c 100644 --- a/src/toml/toml_parser.zig +++ b/src/toml/toml_parser.zig @@ -95,7 +95,7 @@ pub const TOML = struct { pub fn e(_: *TOML, t: anytype, loc: logger.Loc) Expr { const Type = @TypeOf(t); - if (@typeInfo(Type) == .Pointer) { + if (@typeInfo(Type) == .pointer) { return Expr.init(std.meta.Child(Type), t.*, loc); } else { return Expr.init(Type, t, loc); diff --git a/src/tracy.zig b/src/tracy.zig index b83c6946abd63d..2ca3874a81c20b 100644 --- a/src/tracy.zig +++ b/src/tracy.zig @@ -531,10 +531,7 @@ fn dlsym(comptime Type: type, comptime symbol: [:0]const u8) ?Type { "tracy.dll", } else .{}; - const RLTD = if (bun.Environment.isMac) - -2 - else - 0; + const RLTD: std.c.RTLD = if (bun.Environment.isMac) @bitCast(@as(i32, -2)) else if (bun.Environment.isLinux) .{} else {}; if (bun.getenvZ("BUN_TRACY_PATH")) |path| { const handle = bun.C.dlopen(&(std.posix.toPosixPath(path) catch unreachable), RLTD); diff --git a/src/trait.zig b/src/trait.zig index 5c3db377499b6b..57bac0db03ed09 100644 --- a/src/trait.zig +++ b/src/trait.zig @@ -14,14 +14,14 @@ pub inline fn isZigString(comptime T: type) bool { return comptime blk: { // Only pointer types can be strings, no optionals const info = @typeInfo(T); - if (info != .Pointer) break :blk false; + if (info != .pointer) break :blk false; - const ptr = &info.Pointer; + const ptr = &info.pointer; // Check for CV qualifiers that would prevent coerction to []const u8 if (ptr.is_volatile or ptr.is_allowzero) break :blk false; // If it's already a slice, simple check. - if (ptr.size == .Slice) { + if (ptr.size == .slice) { break :blk ptr.child == u8; } @@ -40,50 +40,50 @@ pub inline fn isZigString(comptime T: type) bool { pub inline fn isSlice(comptime T: type) bool { const info = @typeInfo(T); - return info == .Pointer and info.Pointer.size == .Slice; + return info == .pointer and info.pointer.size == .slice; } pub inline fn isNumber(comptime T: type) bool { return switch (@typeInfo(T)) { - .Int, .Float, .ComptimeInt, .ComptimeFloat => true, + .int, .float, .comptime_int, .comptime_float => true, else => false, }; } pub inline fn isContainer(comptime T: type) bool { return switch (@typeInfo(T)) { - .Struct, .Enum, .Opaque, .Union => true, + .@"struct", .@"enum", .@"opaque", .@"union" => true, else => false, }; } pub inline fn isSingleItemPtr(comptime T: type) bool { const info = @typeInfo(T); - return info == .Pointer and .Pointer.size == .One; + return info == .pointer and .pointer.size == .One; } pub fn isExternContainer(comptime T: type) bool { return switch (@typeInfo(T)) { - .Struct => |s| s.layout == .@"extern", - .Union => |u| u.layout == .@"extern", + .@"struct" => |s| s.layout == .@"extern", + .@"union" => |u| u.layout == .@"extern", else => false, }; } pub fn isConstPtr(comptime T: type) bool { const info = @typeInfo(T); - return info == .Pointer and info.Pointer.is_const; + return info == .pointer and info.pointer.is_const; } pub fn isIndexable(comptime T: type) bool { const info = @typeInfo(T); return switch (info) { - .Pointer => |ptr| switch (ptr.size) { - .One => @typeInfo(ptr.child) == .Array, + .pointer => |ptr| switch (ptr.size) { + .One => @typeInfo(ptr.child) == .array, else => true, }, - .Array, .Vector => true, - .Struct => |s| s.is_tuple, + .array, .vector => true, + .@"struct" => |s| s.is_tuple, else => false, }; } diff --git a/src/transpiler.zig b/src/transpiler.zig index edcda26226940f..acaf18b6388248 100644 --- a/src/transpiler.zig +++ b/src/transpiler.zig @@ -53,16 +53,8 @@ const JSC = bun.JSC; const PackageManager = @import("./install/install.zig").PackageManager; const DataURL = @import("./resolver/data_url.zig").DataURL; -pub fn MacroJSValueType_() type { - if (comptime JSC.is_bindgen) { - return struct { - pub const zero = @This(){}; - }; - } - return JSC.JSValue; -} -pub const MacroJSValueType = MacroJSValueType_(); -const default_macro_js_value = if (JSC.is_bindgen) MacroJSValueType{} else JSC.JSValue.zero; +pub const MacroJSValueType = JSC.JSValue; +const default_macro_js_value = JSC.JSValue.zero; const EntryPoints = @import("./bundler/entry_points.zig"); const SystemTimer = @import("./system_timer.zig").Timer; @@ -561,6 +553,7 @@ pub const Transpiler = struct { const has_production_env = this.env.isProduction(); if (!was_production and has_production_env) { this.options.setProduction(true); + this.resolver.opts.setProduction(true); } if (this.options.isTest() or this.env.isTest()) { @@ -575,6 +568,7 @@ pub const Transpiler = struct { this.env.loadProcess(); if (this.env.isProduction()) { this.options.setProduction(true); + this.resolver.opts.setProduction(true); } }, else => {}, @@ -598,7 +592,7 @@ pub const Transpiler = struct { try this.runEnvLoader(false); - this.options.jsx.setProduction(this.env.isProduction()); + var is_production = this.env.isProduction(); js_ast.Expr.Data.Store.create(); js_ast.Stmt.Data.Store.create(); @@ -608,11 +602,26 @@ pub const Transpiler = struct { try this.options.loadDefines(this.allocator, this.env, &this.options.env); + var is_development = false; if (this.options.define.dots.get("NODE_ENV")) |NODE_ENV| { - if (NODE_ENV.len > 0 and NODE_ENV[0].data.value == .e_string and NODE_ENV[0].data.value.e_string.eqlComptime("production")) { - this.options.production = true; + if (NODE_ENV.len > 0 and NODE_ENV[0].data.value == .e_string) { + if (NODE_ENV[0].data.value.e_string.eqlComptime("production")) { + is_production = true; + } else if (NODE_ENV[0].data.value.e_string.eqlComptime("development")) { + is_development = true; + } } } + + if (is_development) { + this.options.setProduction(false); + this.resolver.opts.setProduction(false); + this.options.force_node_env = .development; + this.resolver.opts.force_node_env = .development; + } else if (is_production) { + this.options.setProduction(true); + this.resolver.opts.setProduction(true); + } } pub fn resetStore(_: *const Transpiler) void { @@ -621,7 +630,7 @@ pub const Transpiler = struct { } pub noinline fn dumpEnvironmentVariables(transpiler: *const Transpiler) void { - @setCold(true); + @branchHint(.cold); const opts = std.json.StringifyOptions{ .whitespace = .indent_2, }; @@ -1332,10 +1341,8 @@ pub const Transpiler = struct { opts.features.top_level_await = true; opts.macro_context = &transpiler.macro_context.?; - if (comptime !JSC.is_bindgen) { - if (target != .bun_macro) { - opts.macro_context.javascript_object = this_parse.macro_js_ctx; - } + if (target != .bun_macro) { + opts.macro_context.javascript_object = this_parse.macro_js_ctx; } opts.features.is_macro_runtime = target == .bun_macro; diff --git a/src/url.zig b/src/url.zig index f96325ade9efd4..c3a31bc9206d95 100644 --- a/src/url.zig +++ b/src/url.zig @@ -1043,8 +1043,7 @@ pub const FormData = struct { comptime { const jsFunctionFromMultipartData = JSC.toJSHostFunction(fromMultipartData); - if (!JSC.is_bindgen) - @export(jsFunctionFromMultipartData, .{ .name = "FormData__jsFunctionFromMultipartData" }); + @export(&jsFunctionFromMultipartData, .{ .name = "FormData__jsFunctionFromMultipartData" }); } pub fn toJSFromMultipartData( diff --git a/src/util.zig b/src/util.zig index fbf2e5838d5cf3..d4eadfcf991579 100644 --- a/src/util.zig +++ b/src/util.zig @@ -82,7 +82,7 @@ pub fn fromEntries( pub fn fromMapLike( comptime Map: type, allocator: std.mem.Allocator, - entries: anytype, + entries: []const struct { @FieldType(Map.KV, "key"), @FieldType(Map.KV, "value") }, ) !Map { var map: Map = undefined; if (comptime @hasField(Map, "allocator")) { @@ -91,11 +91,10 @@ pub fn fromMapLike( map = Map{}; } - try map.ensureUnusedCapacity(entries.count()); + try map.ensureUnusedCapacity(allocator, entries.len); - var iter = entries.iterator(); - while (iter.next()) |entry| { - map.putAssumeCapacityNoClobber(entry.key_ptr.*, entry.value_ptr.*); + for (entries) |entry| { + map.putAssumeCapacityNoClobber(entry[0], entry[1]); } return map; @@ -156,11 +155,11 @@ pub inline fn from( return fromEntries(Array, allocator, DefaultType, default); } - if (comptime @typeInfo(DefaultType) == .Struct) { + if (comptime @typeInfo(DefaultType) == .@"struct") { return fromSlice(Array, allocator, DefaultType, default); } - if (comptime @typeInfo(DefaultType) == .Array) { + if (comptime @typeInfo(DefaultType) == .array) { return fromSlice(Array, allocator, []const Of(Array), @as([]const Of(Array), &default)); } diff --git a/src/watcher.zig b/src/watcher.zig index 7639bc11bed75f..3f710c64ceb354 100644 --- a/src/watcher.zig +++ b/src/watcher.zig @@ -333,11 +333,11 @@ fn appendFileAssumeCapacity( // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html var event = std.mem.zeroes(KEvent); - event.flags = std.c.EV_ADD | std.c.EV_CLEAR | std.c.EV_ENABLE; + event.flags = std.c.EV.ADD | std.c.EV.CLEAR | std.c.EV.ENABLE; // we want to know about the vnode - event.filter = std.c.EVFILT_VNODE; + event.filter = std.c.EVFILT.VNODE; - event.fflags = std.c.NOTE_WRITE | std.c.NOTE_RENAME | std.c.NOTE_DELETE; + event.fflags = std.c.NOTE.WRITE | std.c.NOTE.RENAME | std.c.NOTE.DELETE; // id event.ident = @intCast(fd.int()); @@ -425,15 +425,15 @@ fn appendDirectoryAssumeCapacity( // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html var event = std.mem.zeroes(KEvent); - event.flags = std.c.EV_ADD | std.c.EV_CLEAR | std.c.EV_ENABLE; + event.flags = std.c.EV.ADD | std.c.EV.CLEAR | std.c.EV.ENABLE; // we want to know about the vnode - event.filter = std.c.EVFILT_VNODE; + event.filter = std.c.EVFILT.VNODE; // monitor: // - Write // - Rename // - Delete - event.fflags = std.c.NOTE_WRITE | std.c.NOTE_RENAME | std.c.NOTE_DELETE; + event.fflags = std.c.NOTE.WRITE | std.c.NOTE.RENAME | std.c.NOTE.DELETE; // id event.ident = @intCast(fd.int()); diff --git a/src/watcher/INotifyWatcher.zig b/src/watcher/INotifyWatcher.zig index 25ba6248e74112..d86694d6338bf3 100644 --- a/src/watcher/INotifyWatcher.zig +++ b/src/watcher/INotifyWatcher.zig @@ -142,7 +142,7 @@ pub fn read(this: *INotifyWatcher) bun.JSC.Maybe([]const *align(1) Event) { .events = std.posix.POLL.IN | std.posix.POLL.ERR, .revents = 0, }}; - var timespec = std.posix.timespec{ .tv_sec = 0, .tv_nsec = this.coalesce_interval }; + var timespec = std.posix.timespec{ .sec = 0, .nsec = this.coalesce_interval }; if ((std.posix.ppoll(&fds, ×pec, null) catch 0) > 0) { inner: while (true) { const rest = this.eventlist_bytes[read_eventlist_bytes.len..]; diff --git a/src/watcher/KEventWatcher.zig b/src/watcher/KEventWatcher.zig index b5c4436d13da9e..e1037db01a3506 100644 --- a/src/watcher/KEventWatcher.zig +++ b/src/watcher/KEventWatcher.zig @@ -28,10 +28,10 @@ pub fn stop(this: *KEventWatcher) void { pub fn watchEventFromKEvent(kevent: KEvent) Watcher.Event { return .{ .op = .{ - .delete = (kevent.fflags & std.c.NOTE_DELETE) > 0, - .metadata = (kevent.fflags & std.c.NOTE_ATTRIB) > 0, - .rename = (kevent.fflags & (std.c.NOTE_RENAME | std.c.NOTE_LINK)) > 0, - .write = (kevent.fflags & std.c.NOTE_WRITE) > 0, + .delete = (kevent.fflags & std.c.NOTE.DELETE) > 0, + .metadata = (kevent.fflags & std.c.NOTE.ATTRIB) > 0, + .rename = (kevent.fflags & (std.c.NOTE.RENAME | std.c.NOTE.LINK)) > 0, + .write = (kevent.fflags & std.c.NOTE.WRITE) > 0, }, .index = @truncate(kevent.udata), }; @@ -59,7 +59,7 @@ pub fn watchLoopCycle(this: *Watcher) bun.JSC.Maybe(void) { // Give the events more time to coalesce if (count < 128 / 2) { const remain = 128 - count; - var timespec = std.posix.timespec{ .tv_sec = 0, .tv_nsec = 100_000 }; + var timespec = std.posix.timespec{ .sec = 0, .nsec = 100_000 }; const extra = std.posix.system.kevent( this.platform.fd.cast(), @as([*]KEvent, changelist[@as(usize, @intCast(count))..].ptr), diff --git a/src/watcher/WindowsWatcher.zig b/src/watcher/WindowsWatcher.zig index 294e9275df4697..9e62d53381e6f5 100644 --- a/src/watcher/WindowsWatcher.zig +++ b/src/watcher/WindowsWatcher.zig @@ -38,7 +38,7 @@ const DirWatcher = struct { // invalidates any EventIterators fn prepare(this: *DirWatcher) bun.JSC.Maybe(void) { - const filter = w.FILE_NOTIFY_CHANGE_FILE_NAME | w.FILE_NOTIFY_CHANGE_DIR_NAME | w.FILE_NOTIFY_CHANGE_LAST_WRITE | w.FILE_NOTIFY_CHANGE_CREATION; + const filter: w.FileNotifyChangeFilter = .{ .file_name = true, .dir_name = true, .last_write = true, .creation = true }; if (w.kernel32.ReadDirectoryChangesW(this.dirHandle, &this.buf, this.buf.len, 1, filter, null, &this.overlapped, null) == 0) { const err = w.kernel32.GetLastError(); log("failed to start watching directory: {s}", .{@tagName(err)}); @@ -117,10 +117,10 @@ pub fn init(this: *WindowsWatcher, root: []const u8) !void { log("failed to open directory for watching: {s}", .{@tagName(err)}); return Error.CreateFileFailed; } - errdefer _ = w.kernel32.CloseHandle(handle); + errdefer _ = bun.windows.CloseHandle(handle); this.iocp = try w.CreateIoCompletionPort(handle, null, 0, 1); - errdefer _ = w.kernel32.CloseHandle(this.iocp); + errdefer _ = bun.windows.CloseHandle(this.iocp); this.watcher = .{ .dirHandle = handle }; diff --git a/src/windows.zig b/src/windows.zig index 8f6cbc5f5e326b..ecf2de533494f8 100644 --- a/src/windows.zig +++ b/src/windows.zig @@ -7,6 +7,7 @@ pub const WORD = windows.WORD; pub const DWORD = windows.DWORD; pub const CHAR = windows.CHAR; pub const BOOL = windows.BOOL; +pub const BOOLEAN = windows.BOOLEAN; pub const LPVOID = windows.LPVOID; pub const LPCVOID = windows.LPCVOID; pub const LPWSTR = windows.LPWSTR; @@ -33,6 +34,7 @@ pub const STATUS_SUCCESS = windows.STATUS_SUCCESS; pub const MOVEFILE_COPY_ALLOWED = 0x2; pub const MOVEFILE_REPLACE_EXISTING = 0x1; pub const MOVEFILE_WRITE_THROUGH = 0x8; +pub const FILETIME = windows.FILETIME; pub const DUPLICATE_SAME_ACCESS = windows.DUPLICATE_SAME_ACCESS; pub const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES; @@ -3259,8 +3261,8 @@ fn Bun__UVSignalHandle__close(signal: *libuv.uv_signal_t) callconv(.C) void { comptime { if (Environment.isWindows) { - @export(Bun__UVSignalHandle__init, .{ .name = "Bun__UVSignalHandle__init" }); - @export(Bun__UVSignalHandle__close, .{ .name = "Bun__UVSignalHandle__close" }); + @export(&Bun__UVSignalHandle__init, .{ .name = "Bun__UVSignalHandle__init" }); + @export(&Bun__UVSignalHandle__close, .{ .name = "Bun__UVSignalHandle__close" }); } } @@ -3658,3 +3660,13 @@ pub const rescle = struct { }; } }; + +pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.winapi) BOOL; +pub extern "kernel32" fn GetFinalPathNameByHandleW(hFile: HANDLE, lpszFilePath: [*]u16, cchFilePath: DWORD, dwFlags: DWORD) callconv(.winapi) DWORD; +pub extern "kernel32" fn DeleteFileW(lpFileName: [*:0]const u16) callconv(.winapi) BOOL; +pub extern "kernel32" fn CreateSymbolicLinkW(lpSymlinkFileName: [*:0]const u16, lpTargetFileName: [*:0]const u16, dwFlags: DWORD) callconv(.winapi) BOOLEAN; +pub extern "kernel32" fn GetCurrentThread() callconv(.winapi) HANDLE; +pub extern "kernel32" fn GetCommandLineW() callconv(.winapi) LPWSTR; +pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*windows.SECURITY_ATTRIBUTES) callconv(.winapi) BOOL; +pub extern "kernel32" fn SetEndOfFile(hFile: HANDLE) callconv(.winapi) BOOL; +pub extern "kernel32" fn GetProcessTimes(in_hProcess: HANDLE, out_lpCreationTime: *FILETIME, out_lpExitTime: *FILETIME, out_lpKernelTime: *FILETIME, out_lpUserTime: *FILETIME) callconv(.winapi) BOOL; diff --git a/src/windows_c.zig b/src/windows_c.zig index f4f6e08c3d6857..8a0dd420014fe3 100644 --- a/src/windows_c.zig +++ b/src/windows_c.zig @@ -27,7 +27,7 @@ pub export fn memmem(haystack: ?[*]const u8, haystacklen: usize, needle: ?[*]con } comptime { - @export(memmem, .{ .name = "zig_memmem" }); + @export(&memmem, .{ .name = "zig_memmem" }); } pub const lstat = blk: { @@ -57,7 +57,7 @@ pub fn getSystemLoadavg() [3]f32 { return .{ 0, 0, 0 }; } -pub const Mode = i32; +pub const Mode = u16; const Win32Error = bun.windows.Win32Error; // The way we do errors in Bun needs to get cleaned up. diff --git a/src/work_pool.zig b/src/work_pool.zig index 380dfacfd8a715..53b04a10027118 100644 --- a/src/work_pool.zig +++ b/src/work_pool.zig @@ -11,7 +11,7 @@ pub fn NewWorkPool(comptime max_threads: ?usize) type { var loaded: bool = false; fn create() *ThreadPool { - @setCold(true); + @branchHint(.cold); pool = ThreadPool.init(.{ .max_threads = max_threads orelse bun.getThreadCount(), diff --git a/test/bun.lock b/test/bun.lock index 4a801e05dd97b0..24ff9e9e496ad6 100644 --- a/test/bun.lock +++ b/test/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "test", @@ -23,7 +23,9 @@ "axios": "1.6.8", "body-parser": "1.20.2", "comlink": "4.4.1", + "commander": "12.1.0", "devalue": "5.1.1", + "duckdb": "1.1.3", "es-module-lexer": "1.3.0", "esbuild": "0.18.6", "express": "4.18.2", @@ -202,6 +204,8 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.6", "", { "os": "win32", "cpu": "x64" }, "sha512-9UDwkz7Wlm4N9jnv+4NL7F8vxLhSZfEkRArz2gD33HesAFfMLGIGNVXRoIHtWNw8feKsnGly9Hq1EUuRkWl0zA=="], + "@gar/promisify": ["@gar/promisify@1.1.3", "", {}, "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="], + "@graphql-yoga/subscription": ["@graphql-yoga/subscription@5.0.3", "", { "dependencies": { "@graphql-yoga/typed-event-target": "^3.0.2", "@repeaterjs/repeater": "^3.0.4", "@whatwg-node/events": "^0.1.0", "tslib": "^2.8.1" } }, "sha512-xLGEataxCULjL9rlTCVFL1IW2E90TnDIL+mE4lZBi9X92jc6s+Q+jk6Ax3I98kryCJh0UMiwjit7CaIIczTiJg=="], "@graphql-yoga/typed-event-target": ["@graphql-yoga/typed-event-target@3.0.2", "", { "dependencies": { "@repeaterjs/repeater": "^3.0.4", "tslib": "^2.8.1" } }, "sha512-ZpJxMqB+Qfe3rp6uszCQoag4nSw42icURnBRfFYSOmTgEeOe4rD0vYlbA8spvCu2TlCesNTlEN9BLWtQqLxabA=="], @@ -332,6 +336,8 @@ "@lukeed/csprng": ["@lukeed/csprng@1.1.0", "", {}, "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA=="], + "@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@1.0.11", "", { "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", "make-dir": "^3.1.0", "node-fetch": "^2.6.7", "nopt": "^5.0.0", "npmlog": "^5.0.1", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.11" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ=="], + "@mongodb-js/saslprep": ["@mongodb-js/saslprep@1.1.7", "", { "dependencies": { "sparse-bitfield": "^3.0.3" } }, "sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q=="], "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ=="], @@ -386,6 +392,8 @@ "@npmcli/fs": ["@npmcli/fs@3.1.1", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg=="], + "@npmcli/move-file": ["@npmcli/move-file@2.0.1", "", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="], + "@nuxt/opencollective": ["@nuxt/opencollective@0.4.1", "", { "dependencies": { "consola": "^3.2.3" }, "bin": { "opencollective": "bin/opencollective.js" } }, "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ=="], "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="], @@ -540,6 +548,8 @@ "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], + "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], + "@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="], "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], @@ -712,6 +722,8 @@ "agent-base": ["agent-base@7.1.1", "", { "dependencies": { "debug": "^4.3.4" } }, "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA=="], + "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], + "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="], "ajv": ["ajv@8.12.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA=="], @@ -734,6 +746,10 @@ "app-root-path": ["app-root-path@3.1.0", "", {}, "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA=="], + "aproba": ["aproba@2.0.0", "", {}, "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="], + + "are-we-there-yet": ["are-we-there-yet@2.0.0", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], @@ -886,13 +902,15 @@ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], + "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], "comlink": ["comlink@4.4.1", "", {}, "sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q=="], - "commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], + "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], "component-emitter": ["component-emitter@1.3.1", "", {}, "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ=="], @@ -908,6 +926,8 @@ "consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="], + "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="], + "constructs": ["constructs@10.3.0", "", {}, "sha512-vbK8i3rIb/xwZxSpTjz3SagHn1qq9BChLEfy5Hf6fB3/2eFbrwt2n9kHwQcS0CPTRBesreeAcsJfMq2229FnbQ=="], "content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], @@ -960,6 +980,8 @@ "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + "delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="], + "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], @@ -984,6 +1006,8 @@ "dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="], + "duckdb": ["duckdb@1.1.3", "", { "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "node-addon-api": "^7.0.0", "node-gyp": "^9.3.0" } }, "sha512-tIpZr2NsSkYmfGC1ETl75RuVsaDyjvR3yAOrECcIyw7bdluzcyzEXOXoiuT+4t54hT+CppZv43gk/HiZdKW9Vw=="], + "duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="], "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], @@ -1134,10 +1158,14 @@ "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + "gauge": ["gauge@3.0.2", "", { "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "object-assign": "^4.1.1", "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" } }, "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q=="], + "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], @@ -1190,6 +1218,8 @@ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + "has-unicode": ["has-unicode@2.0.1", "", {}, "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="], + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="], @@ -1220,6 +1250,8 @@ "human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], + "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -1238,6 +1270,10 @@ "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "infer-owner": ["infer-owner@1.0.4", "", {}, "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="], + + "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=="], "interpret": ["interpret@2.2.0", "", {}, "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw=="], @@ -1410,6 +1446,8 @@ "magic-string": ["magic-string@0.30.14", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw=="], + "make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], + "make-fetch-happen": ["make-fetch-happen@13.0.1", "", { "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", "http-cache-semantics": "^4.1.1", "is-lambda": "^1.0.1", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" } }, "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA=="], "md5-hex": ["md5-hex@3.0.1", "", { "dependencies": { "blueimp-md5": "^2.10.0" } }, "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw=="], @@ -1444,7 +1482,7 @@ "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - "minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="], + "minipass-collect": ["minipass-collect@1.0.2", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="], "minipass-fetch": ["minipass-fetch@3.0.5", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg=="], @@ -1494,6 +1532,8 @@ "nise": ["nise@1.5.3", "", { "dependencies": { "@sinonjs/formatio": "^3.2.1", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "lolex": "^5.0.1", "path-to-regexp": "^1.7.0" } }, "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ=="], + "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], + "node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="], "node-gyp": ["node-gyp@10.0.1", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^10.3.10", "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", "proc-log": "^3.0.0", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^4.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg=="], @@ -1510,6 +1550,8 @@ "npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="], + "npmlog": ["npmlog@5.0.1", "", { "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", "gauge": "^3.0.0", "set-blocking": "^2.0.0" } }, "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw=="], + "nwsapi": ["nwsapi@2.2.16", "", {}, "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -1568,6 +1610,8 @@ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], @@ -1656,6 +1700,8 @@ "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], + "promise-inflight": ["promise-inflight@1.0.1", "", {}, "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="], + "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="], "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], @@ -1746,6 +1792,8 @@ "rhea-promise": ["rhea-promise@3.0.3", "", { "dependencies": { "debug": "^4.0.0", "rhea": "^3.0.0", "tslib": "^2.6.0" } }, "sha512-a875P5YcMkePSTEWMsnmCQS7Y4v/XvIw7ZoMtJxqtQRZsqSA6PsZxuz4vktyRykPuUgdNsA6F84dS3iEXZoYnQ=="], + "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + "rollup": ["rollup@4.4.1", "", { "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.4.1", "@rollup/rollup-android-arm64": "4.4.1", "@rollup/rollup-darwin-arm64": "4.4.1", "@rollup/rollup-darwin-x64": "4.4.1", "@rollup/rollup-linux-arm-gnueabihf": "4.4.1", "@rollup/rollup-linux-arm64-gnu": "4.4.1", "@rollup/rollup-linux-arm64-musl": "4.4.1", "@rollup/rollup-linux-x64-gnu": "4.4.1", "@rollup/rollup-linux-x64-musl": "4.4.1", "@rollup/rollup-win32-arm64-msvc": "4.4.1", "@rollup/rollup-win32-ia32-msvc": "4.4.1", "@rollup/rollup-win32-x64-msvc": "4.4.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-idZzrUpWSblPJX66i+GzrpjKE3vbYrlWirUHteoAbjKReZwa0cohAErOYA5efoMmNCdvG9yrJS+w9Kl6csaH4w=="], "rrweb-cssom": ["rrweb-cssom@0.7.1", "", {}, "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg=="], @@ -1784,6 +1832,8 @@ "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=="], + "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], + "set-cookie-parser": ["set-cookie-parser@2.6.0", "", {}, "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ=="], "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], @@ -1828,7 +1878,7 @@ "socks": ["socks@2.8.3", "", { "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw=="], - "socks-proxy-agent": ["socks-proxy-agent@8.0.3", "", { "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", "socks": "^2.7.1" } }, "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A=="], + "socks-proxy-agent": ["socks-proxy-agent@7.0.0", "", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="], "sonic-boom": ["sonic-boom@4.1.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw=="], @@ -2074,6 +2124,8 @@ "why-is-node-running": ["why-is-node-running@2.2.2", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA=="], + "wide-align": ["wide-align@1.1.5", "", { "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg=="], + "wildcard": ["wildcard@2.0.1", "", {}, "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ=="], "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], @@ -2160,6 +2212,12 @@ "@jridgewell/trace-mapping/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.15", "", {}, "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="], + "@mapbox/node-pre-gyp/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "@mapbox/node-pre-gyp/nopt": ["nopt@5.0.0", "", { "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ=="], + + "@mapbox/node-pre-gyp/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "@nestjs/common/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "@nestjs/core/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -2168,6 +2226,10 @@ "@npmcli/agent/lru-cache": ["lru-cache@10.2.2", "", {}, "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ=="], + "@npmcli/agent/socks-proxy-agent": ["socks-proxy-agent@8.0.3", "", { "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", "socks": "^2.7.1" } }, "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A=="], + + "@npmcli/move-file/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + "@puppeteer/browsers/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], "@puppeteer/browsers/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], @@ -2250,6 +2312,8 @@ "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], + "are-we-there-yet/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "async-cache/lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="], "basic-auth/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], @@ -2264,6 +2328,8 @@ "cacache/lru-cache": ["lru-cache@10.2.2", "", {}, "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ=="], + "cacache/minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="], + "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "cli-highlight/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -2286,6 +2352,8 @@ "debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "duckdb/node-gyp": ["node-gyp@9.4.1", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ=="], + "duplexify/readable-stream": ["readable-stream@2.3.8", "", { "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-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "ecc-jsbn/jsbn": ["jsbn@0.1.1", "", {}, "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="], @@ -2322,6 +2390,10 @@ "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "gauge/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=="], + + "gauge/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "get-uri/data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], "get-uri/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], @@ -2352,8 +2424,12 @@ "jsonwebtoken/jws": ["jws@3.2.2", "", { "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA=="], + "make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "make-fetch-happen/proc-log": ["proc-log@4.2.0", "", {}, "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA=="], + "minipass-collect/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], @@ -2406,6 +2482,8 @@ "proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + "proxy-agent/socks-proxy-agent": ["socks-proxy-agent@8.0.3", "", { "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", "socks": "^2.7.1" } }, "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A=="], + "pumpify/pump": ["pump@2.0.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA=="], "puppeteer-core/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], @@ -2424,6 +2502,8 @@ "rhea-promise/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + "rimraf/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=="], + "rxjs/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "sass/chokidar": ["chokidar@4.0.1", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA=="], @@ -2442,7 +2522,9 @@ "socket.io-parser/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], - "socks-proxy-agent/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + "socks-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "socks-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], @@ -2524,6 +2606,10 @@ "webpack-cli/colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="], + "webpack-cli/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], + + "wide-align/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=="], + "wrap-ansi/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=="], "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -2548,8 +2634,16 @@ "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + "@mapbox/node-pre-gyp/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "@mapbox/node-pre-gyp/https-proxy-agent/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + + "@mapbox/node-pre-gyp/nopt/abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + "@npmcli/agent/https-proxy-agent/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + "@npmcli/agent/socks-proxy-agent/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + "@remix-run/serve/express/cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], "@remix-run/serve/express/path-to-regexp": ["path-to-regexp@0.1.7", "", {}, "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="], @@ -2616,6 +2710,18 @@ "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "duckdb/node-gyp/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=="], + + "duckdb/node-gyp/make-fetch-happen": ["make-fetch-happen@10.2.1", "", { "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" } }, "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w=="], + + "duckdb/node-gyp/nopt": ["nopt@6.0.0", "", { "dependencies": { "abbrev": "^1.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g=="], + + "duckdb/node-gyp/npmlog": ["npmlog@6.0.2", "", { "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", "gauge": "^4.0.3", "set-blocking": "^2.0.0" } }, "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg=="], + + "duckdb/node-gyp/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + + "duckdb/node-gyp/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + "duplexify/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], "duplexify/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], @@ -2630,6 +2736,10 @@ "express/body-parser/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=="], + "gauge/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "gauge/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "http-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], @@ -2654,6 +2764,8 @@ "node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "proxy-agent/socks-proxy-agent/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + "rhea-promise/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], "rhea/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], @@ -2670,7 +2782,7 @@ "socket.io/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], - "socks-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "socks-proxy-agent/agent-base/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -2780,6 +2892,10 @@ "vitest/magic-string/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.15", "", {}, "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="], + "wide-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wide-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -2798,8 +2914,12 @@ "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@mapbox/node-pre-gyp/https-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "@npmcli/agent/https-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "@npmcli/agent/socks-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "@testing-library/dom/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], "@verdaccio/middleware/express/body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], @@ -2818,10 +2938,36 @@ "cli-highlight/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "duckdb/node-gyp/make-fetch-happen/cacache": ["cacache@16.1.3", "", { "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" } }, "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ=="], + + "duckdb/node-gyp/make-fetch-happen/http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], + + "duckdb/node-gyp/make-fetch-happen/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "duckdb/node-gyp/make-fetch-happen/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + + "duckdb/node-gyp/make-fetch-happen/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "duckdb/node-gyp/make-fetch-happen/minipass-fetch": ["minipass-fetch@2.1.2", "", { "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA=="], + + "duckdb/node-gyp/make-fetch-happen/ssri": ["ssri@9.0.1", "", { "dependencies": { "minipass": "^3.1.1" } }, "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q=="], + + "duckdb/node-gyp/nopt/abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "duckdb/node-gyp/npmlog/are-we-there-yet": ["are-we-there-yet@3.0.1", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg=="], + + "duckdb/node-gyp/npmlog/gauge": ["gauge@4.0.4", "", { "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", "console-control-strings": "^1.1.0", "has-unicode": "^2.0.1", "signal-exit": "^3.0.7", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.5" } }, "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg=="], + + "duckdb/node-gyp/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "jest-diff/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], "msw/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "proxy-agent/socks-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + + "socks-proxy-agent/agent-base/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + "typeorm/chalk/supports-color/has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], "verdaccio-audit/express/body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], @@ -2840,10 +2986,50 @@ "verdaccio/express/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + "wide-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "cli-highlight/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/@npmcli/fs": ["@npmcli/fs@2.1.2", "", { "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/unique-filename": ["unique-filename@2.0.1", "", { "dependencies": { "unique-slug": "^3.0.0" } }, "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A=="], + + "duckdb/node-gyp/make-fetch-happen/http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "duckdb/node-gyp/make-fetch-happen/http-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + + "duckdb/node-gyp/make-fetch-happen/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "duckdb/node-gyp/make-fetch-happen/https-proxy-agent/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + + "duckdb/node-gyp/npmlog/are-we-there-yet/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "duckdb/node-gyp/npmlog/gauge/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=="], + + "duckdb/node-gyp/npmlog/gauge/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/unique-filename/unique-slug": ["unique-slug@3.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w=="], + + "duckdb/node-gyp/make-fetch-happen/http-proxy-agent/agent-base/debug": ["debug@4.3.5", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg=="], + + "duckdb/node-gyp/make-fetch-happen/https-proxy-agent/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + + "duckdb/node-gyp/npmlog/gauge/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "duckdb/node-gyp/npmlog/gauge/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "duckdb/node-gyp/make-fetch-happen/cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "duckdb/node-gyp/make-fetch-happen/http-proxy-agent/agent-base/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], } } diff --git a/test/bundler/native_plugin.cc b/test/bundler/native_plugin.cc index 707d28fd66fd85..e3a38c9281385c 100644 --- a/test/bundler/native_plugin.cc +++ b/test/bundler/native_plugin.cc @@ -559,8 +559,9 @@ napi_value Init(napi_env env, napi_value exports) { "Failed to add create_external function to exports"); return nullptr; } - - return exports; + // this should be the same as returning `exports`, but it would crash in + // previous versions of Bun + return nullptr; } struct NewOnBeforeParseArguments { diff --git a/test/bundler/transpiler/jsx-dev/jsx-dev.tsx b/test/bundler/transpiler/jsx-dev/jsx-dev.tsx new file mode 100644 index 00000000000000..ee854a800268c0 --- /dev/null +++ b/test/bundler/transpiler/jsx-dev/jsx-dev.tsx @@ -0,0 +1,37 @@ +import { renderToReadableStream } from "react-dom/server.browser"; + +const HelloWorld = () => { + return
Hello World
; +}; + +const stream = new Response(await renderToReadableStream()); + +console.log(await stream.text()); + +if (!process.env.NO_BUILD) { + const self = await Bun.build({ + entrypoints: [import.meta.path], + define: { + "process.env.NODE_ENV": JSON.stringify(process.env.CHILD_NODE_ENV), + "process.env.NO_BUILD": "1", + }, + }); + const code = await self.outputs[0].text(); + let shouldHaveJSXDev = process.env.CHILD_NODE_ENV === "development"; + let shouldHaveJSX = process.env.CHILD_NODE_ENV === "production"; + + if (shouldHaveJSXDev) { + if (!code.includes("jsx_dev_runtime.jsxDEV")) { + throw new Error("jsxDEV is not included"); + } + } + + if (shouldHaveJSX) { + if (!code.includes("jsx_runtime.jsx")) { + throw new Error("Jsx is not included"); + } + } + + const url = URL.createObjectURL(self.outputs[0]); + await import(url); +} diff --git a/test/bundler/transpiler/jsx-dev/tsconfig.json b/test/bundler/transpiler/jsx-dev/tsconfig.json new file mode 100644 index 00000000000000..12a075f81a9734 --- /dev/null +++ b/test/bundler/transpiler/jsx-dev/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "react-jsxdev" + } +} diff --git a/test/bundler/transpiler/jsx-production-entry.ts b/test/bundler/transpiler/jsx-production-entry.ts new file mode 100644 index 00000000000000..eec766abee1578 --- /dev/null +++ b/test/bundler/transpiler/jsx-production-entry.ts @@ -0,0 +1 @@ +import "./jsx-production"; diff --git a/test/bundler/transpiler/jsx-production.test.ts b/test/bundler/transpiler/jsx-production.test.ts new file mode 100644 index 00000000000000..7fd7ad30d3062b --- /dev/null +++ b/test/bundler/transpiler/jsx-production.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, test, afterAll } from "bun:test"; +import path from "path"; +import { bunExe, bunEnv } from "harness"; + +const original_node_env = bunEnv.NODE_ENV; + +// https://github.com/oven-sh/bun/issues/3768 +describe("jsx", () => { + for (const node_env of ["production", "development", "test", ""]) { + for (const child_node_env of ["production", "development", "test", ""]) { + test(`react-jsxDEV parent: ${node_env} child: ${child_node_env} should work`, async () => { + bunEnv.NODE_ENV = node_env; + bunEnv.CHILD_NODE_ENV = child_node_env; + bunEnv.TSCONFIG_JSX = "react-jsxdev"; + expect([path.join(import.meta.dirname, "jsx-dev", "jsx-dev.tsx")]).toRun( + "
Hello World
" + "\n" + "
Hello World
" + "\n", + ); + }); + + test(`react-jsx parent: ${node_env} child: ${child_node_env} should work`, async () => { + bunEnv.NODE_ENV = node_env; + bunEnv.CHILD_NODE_ENV = child_node_env; + bunEnv.TSCONFIG_JSX = "react-jsx"; + expect([path.join(import.meta.dirname, "jsx-production-entry.ts")]).toRun( + "
Hello World
" + "\n" + "
Hello World
" + "\n", + ); + }); + } + } + + afterAll(() => { + bunEnv.NODE_ENV = original_node_env; + delete bunEnv.CHILD_NODE_ENV; + delete bunEnv.TSCONFIG_JSX; + }); +}); diff --git a/test/bundler/transpiler/jsx-production.tsx b/test/bundler/transpiler/jsx-production.tsx new file mode 100644 index 00000000000000..ee854a800268c0 --- /dev/null +++ b/test/bundler/transpiler/jsx-production.tsx @@ -0,0 +1,37 @@ +import { renderToReadableStream } from "react-dom/server.browser"; + +const HelloWorld = () => { + return
Hello World
; +}; + +const stream = new Response(await renderToReadableStream()); + +console.log(await stream.text()); + +if (!process.env.NO_BUILD) { + const self = await Bun.build({ + entrypoints: [import.meta.path], + define: { + "process.env.NODE_ENV": JSON.stringify(process.env.CHILD_NODE_ENV), + "process.env.NO_BUILD": "1", + }, + }); + const code = await self.outputs[0].text(); + let shouldHaveJSXDev = process.env.CHILD_NODE_ENV === "development"; + let shouldHaveJSX = process.env.CHILD_NODE_ENV === "production"; + + if (shouldHaveJSXDev) { + if (!code.includes("jsx_dev_runtime.jsxDEV")) { + throw new Error("jsxDEV is not included"); + } + } + + if (shouldHaveJSX) { + if (!code.includes("jsx_runtime.jsx")) { + throw new Error("Jsx is not included"); + } + } + + const url = URL.createObjectURL(self.outputs[0]); + await import(url); +} diff --git a/test/bundler/transpiler/tsconfig.json b/test/bundler/transpiler/tsconfig.json new file mode 100644 index 00000000000000..2431b86fe43ab9 --- /dev/null +++ b/test/bundler/transpiler/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "react-jsx" + } +} diff --git a/test/cli/install/__snapshots__/bun-lock.test.ts.snap b/test/cli/install/__snapshots__/bun-lock.test.ts.snap index 5c92ce56763c42..2523c5077033ac 100644 --- a/test/cli/install/__snapshots__/bun-lock.test.ts.snap +++ b/test/cli/install/__snapshots__/bun-lock.test.ts.snap @@ -121,3 +121,286 @@ exports[`should save the lockfile if --save-text-lockfile and --frozen-lockfile } " `; + +exports[`should convert a binary lockfile with invalid optional peers 1`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "eassist", + "dependencies": { + "langchain": "^0.0.194", + }, + }, + }, + "packages": { + "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.9.1", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "digest-fetch": "^1.3.0", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7", "web-streams-polyfill": "^3.2.1" } }, "sha512-wa1meQ2WSfoY8Uor3EdrJq0jTiZJoKoSii2ZVWRY1oN4Tlr5s59pADg9T79FTbPe1/se5c3pBeZgJL63wmuoBA=="], + + "@types/node": ["@types/node@18.18.11", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-c1vku6qnTeujJneYH94/4aq73XrVcsJe35UPyAsSok1ijiKrkRzK+AxQPSpNMUnC03roWBBwJx/9I8V7lQoxmA=="], + + "@types/node-fetch": ["@types/node-fetch@2.6.9", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.0" } }, "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA=="], + + "@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], + + "@types/uuid": ["@types/uuid@9.0.7", "", {}, "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g=="], + + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], + + "agentkeepalive": ["agentkeepalive@4.5.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew=="], + + "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "base-64": ["base-64@0.1.0", "", {}, "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "binary-extensions": ["binary-extensions@2.2.0", "", {}, "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="], + + "binary-search": ["binary-search@1.3.6", "", {}, "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="], + + "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], + + "charenc": ["charenc@0.0.2", "", {}, "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + + "crypt": ["crypt@0.0.2", "", {}, "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="], + + "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "digest-fetch": ["digest-fetch@1.3.0", "", { "dependencies": { "base-64": "^0.1.0", "md5": "^2.3.0" } }, "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA=="], + + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + + "eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], + + "expr-eval": ["expr-eval@2.0.2", "", {}, "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg=="], + + "flat": ["flat@5.0.2", "", { "bin": { "flat": "cli.js" } }, "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="], + + "form-data": ["form-data@4.0.0", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww=="], + + "form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="], + + "formdata-node": ["formdata-node@4.4.1", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" } }, "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ=="], + + "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], + + "is-any-array": ["is-any-array@2.0.1", "", {}, "sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ=="], + + "is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="], + + "js-tiktoken": ["js-tiktoken@1.0.8", "", { "dependencies": { "base64-js": "^1.5.1" } }, "sha512-r7XK3E9/I+SOrbAGqb39pyO/rHAS1diAOSRAvaaLfHgXjkUSK9AiSd+r84Vn2f/GvXJYRAxKj8NHrUvqlaH5qg=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="], + + "langchain": ["langchain@0.0.194", "", { "dependencies": { "@anthropic-ai/sdk": "^0.9.1", "ansi-styles": "^5.0.0", "binary-extensions": "^2.2.0", "camelcase": "6", "decamelize": "^1.2.0", "expr-eval": "^2.0.2", "flat": "^5.0.2", "js-tiktoken": "^1.0.7", "js-yaml": "^4.1.0", "jsonpointer": "^5.0.1", "langchainhub": "~0.0.6", "langsmith": "~0.0.48", "ml-distance": "^4.0.0", "openai": "^4.19.0", "openapi-types": "^12.1.3", "p-queue": "^6.6.2", "p-retry": "4", "uuid": "^9.0.0", "yaml": "^2.2.1", "zod": "^3.22.3", "zod-to-json-schema": "3.20.3" }, "peerDependencies": { "@aws-crypto/sha256-js": "^5.0.0", "@aws-sdk/client-bedrock-runtime": "^3.422.0", "@aws-sdk/client-dynamodb": "^3.310.0", "@aws-sdk/client-kendra": "^3.352.0", "@aws-sdk/client-lambda": "^3.310.0", "@aws-sdk/client-s3": "^3.310.0", "@aws-sdk/client-sagemaker-runtime": "^3.310.0", "@aws-sdk/client-sfn": "^3.310.0", "@aws-sdk/credential-provider-node": "^3.388.0", "@azure/storage-blob": "^12.15.0", "@clickhouse/client": "^0.0.14", "@cloudflare/ai": "^1.0.12", "@elastic/elasticsearch": "^8.4.0", "@getmetal/metal-sdk": "*", "@getzep/zep-js": "^0.9.0", "@gomomento/sdk": "^1.47.1", "@gomomento/sdk-core": "^1.47.1", "@gomomento/sdk-web": "^1.47.1", "@google-ai/generativelanguage": "^0.2.1", "@google-cloud/storage": "^6.10.1", "@huggingface/inference": "^2.6.4", "@mozilla/readability": "*", "@notionhq/client": "^2.2.10", "@opensearch-project/opensearch": "*", "@pinecone-database/pinecone": "^1.1.0", "@planetscale/database": "^1.8.0", "@qdrant/js-client-rest": "^1.2.0", "@raycast/api": "^1.55.2", "@rockset/client": "^0.9.1", "@smithy/eventstream-codec": "^2.0.5", "@smithy/protocol-http": "^3.0.6", "@smithy/signature-v4": "^2.0.10", "@smithy/util-utf8": "^2.0.0", "@supabase/postgrest-js": "^1.1.1", "@supabase/supabase-js": "^2.10.0", "@tensorflow-models/universal-sentence-encoder": "*", "@tensorflow/tfjs-converter": "*", "@tensorflow/tfjs-core": "*", "@upstash/redis": "^1.20.6", "@vercel/kv": "^0.2.3", "@vercel/postgres": "^0.5.0", "@writerai/writer-sdk": "^0.40.2", "@xata.io/client": "^0.25.1", "@xenova/transformers": "^2.5.4", "@zilliz/milvus2-sdk-node": ">=2.2.7", "apify-client": "^2.7.1", "assemblyai": "^2.0.2", "axios": "*", "cassandra-driver": "^4.7.2", "cheerio": "^1.0.0-rc.12", "chromadb": "*", "closevector-common": "0.1.0-alpha.1", "closevector-node": "0.1.0-alpha.10", "closevector-web": "0.1.0-alpha.16", "cohere-ai": ">=6.0.0", "convex": "^1.3.1", "d3-dsv": "^2.0.0", "epub2": "^3.0.1", "faiss-node": "^0.5.1", "fast-xml-parser": "^4.2.7", "firebase-admin": "^11.9.0", "google-auth-library": "^8.9.0", "googleapis": "^126.0.1", "hnswlib-node": "^1.4.2", "html-to-text": "^9.0.5", "ignore": "^5.2.0", "ioredis": "^5.3.2", "jsdom": "*", "llmonitor": "^0.5.9", "lodash": "^4.17.21", "mammoth": "*", "mongodb": "^5.2.0", "mysql2": "^3.3.3", "neo4j-driver": "*", "node-llama-cpp": "*", "notion-to-md": "^3.1.0", "pdf-parse": "1.1.1", "peggy": "^3.0.2", "pg": "^8.11.0", "pg-copy-streams": "^6.0.5", "pickleparser": "^0.2.1", "playwright": "^1.32.1", "portkey-ai": "^0.1.11", "puppeteer": "^19.7.2", "redis": "^4.6.4", "replicate": "^0.18.0", "sonix-speech-recognition": "^2.1.1", "srt-parser-2": "^1.2.2", "typeorm": "^0.3.12", "typesense": "^1.5.3", "usearch": "^1.1.1", "vectordb": "^0.1.4", "voy-search": "0.6.2", "weaviate-ts-client": "^1.4.0", "web-auth-library": "^1.0.3", "ws": "^8.14.2", "youtube-transcript": "^1.0.6", "youtubei.js": "^5.8.0" }, "optionalPeers": ["@aws-crypto/sha256-js", "@aws-sdk/client-bedrock-runtime", "@aws-sdk/client-dynamodb", "@aws-sdk/client-kendra", "@aws-sdk/client-lambda", "@aws-sdk/client-s3", "@aws-sdk/client-sagemaker-runtime", "@aws-sdk/client-sfn", "@aws-sdk/credential-provider-node", "@azure/storage-blob", "@clickhouse/client", "@cloudflare/ai", "@elastic/elasticsearch", "@getmetal/metal-sdk", "@getzep/zep-js", "@gomomento/sdk", "@gomomento/sdk-core", "@gomomento/sdk-web", "@google-ai/generativelanguage", "@google-cloud/storage", "@huggingface/inference", "@mozilla/readability", "@notionhq/client", "@opensearch-project/opensearch", "@pinecone-database/pinecone", "@planetscale/database", "@qdrant/js-client-rest", "@raycast/api", "@rockset/client", "@smithy/eventstream-codec", "@smithy/protocol-http", "@smithy/signature-v4", "@smithy/util-utf8", "@supabase/postgrest-js", "@supabase/supabase-js", "@tensorflow-models/universal-sentence-encoder", "@tensorflow/tfjs-converter", "@tensorflow/tfjs-core", "@upstash/redis", "@vercel/kv", "@vercel/postgres", "@writerai/writer-sdk", "@xata.io/client", "@xenova/transformers", "@zilliz/milvus2-sdk-node", "apify-client", "assemblyai", "axios", "cassandra-driver", "cheerio", "chromadb", "closevector-common", "closevector-node", "closevector-web", "cohere-ai", "convex", "d3-dsv", "epub2", "faiss-node", "fast-xml-parser", "firebase-admin", "google-auth-library", "googleapis", "hnswlib-node", "html-to-text", "ignore", "ioredis", "jsdom", "llmonitor", "lodash", "mammoth", "mongodb", "mysql2", "neo4j-driver", "node-llama-cpp", "notion-to-md", "pdf-parse", "peggy", "pg", "pg-copy-streams", "pickleparser", "playwright", "portkey-ai", "puppeteer", "redis", "replicate", "sonix-speech-recognition", "srt-parser-2", "typeorm", "typesense", "usearch", "vectordb", "voy-search", "weaviate-ts-client", "web-auth-library", "ws", "youtube-transcript", "youtubei.js"] }, "sha512-EbpVWL0l5V2byMmEnHf+xpkpPWQ1CgFINjM1RPk6+D3zm7HtkOWYoU0gTrWA5mmL9L1EB1w8r1xIh8E63Ts/HQ=="], + + "langchainhub": ["langchainhub@0.0.6", "", {}, "sha512-SW6105T+YP1cTe0yMf//7kyshCgvCTyFBMTgH2H3s9rTAR4e+78DA/BBrUL/Mt4Q5eMWui7iGuAYb3pgGsdQ9w=="], + + "langsmith": ["langsmith@0.0.48", "", { "dependencies": { "@types/uuid": "^9.0.1", "commander": "^10.0.1", "p-queue": "^6.6.2", "p-retry": "4", "uuid": "^9.0.0" }, "bin": { "langsmith": "dist/cli/main.cjs" } }, "sha512-s0hW8iZ90Q9XLTnDK0Pgee245URV3b1cXQjPDj5OKm1+KN7iSK1pKx+4CO7RcFLz58Ixe7Mt+mVcomYqUuryxQ=="], + + "md5": ["md5@2.3.0", "", { "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", "is-buffer": "~1.1.6" } }, "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g=="], + + "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=="], + + "ml-array-mean": ["ml-array-mean@1.1.6", "", { "dependencies": { "ml-array-sum": "^1.1.6" } }, "sha512-MIdf7Zc8HznwIisyiJGRH9tRigg3Yf4FldW8DxKxpCCv/g5CafTw0RRu51nojVEOXuCQC7DRVVu5c7XXO/5joQ=="], + + "ml-array-sum": ["ml-array-sum@1.1.6", "", { "dependencies": { "is-any-array": "^2.0.0" } }, "sha512-29mAh2GwH7ZmiRnup4UyibQZB9+ZLyMShvt4cH4eTK+cL2oEMIZFnSyB3SS8MlsTh6q/w/yh48KmqLxmovN4Dw=="], + + "ml-distance": ["ml-distance@4.0.1", "", { "dependencies": { "ml-array-mean": "^1.1.6", "ml-distance-euclidean": "^2.0.0", "ml-tree-similarity": "^1.0.0" } }, "sha512-feZ5ziXs01zhyFUUUeZV5hwc0f5JW0Sh0ckU1koZe/wdVkJdGxcP06KNQuF0WBTj8FttQUzcvQcpcrOp/XrlEw=="], + + "ml-distance-euclidean": ["ml-distance-euclidean@2.0.0", "", {}, "sha512-yC9/2o8QF0A3m/0IXqCTXCzz2pNEzvmcE/9HFKOZGnTjatvBbsn4lWYJkxENkA4Ug2fnYl7PXQxnPi21sgMy/Q=="], + + "ml-tree-similarity": ["ml-tree-similarity@1.0.0", "", { "dependencies": { "binary-search": "^1.3.5", "num-sort": "^2.0.0" } }, "sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "num-sort": ["num-sort@2.1.0", "", {}, "sha512-1MQz1Ed8z2yckoBeSfkQHHO9K1yDRxxtotKSJ9yvcTUUxSvfvzEq5GwBrjjHEpMlq/k5gvXdmJ1SbYxWtpNoVg=="], + + "openai": ["openai@4.19.1", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "digest-fetch": "^1.3.0", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7", "web-streams-polyfill": "^3.2.1" }, "bin": { "openai": "bin/cli" } }, "sha512-9TddzuZBn2xxhghGGTHLZ4EeNBGTLs3xVzh266NiSJvtUsCsZQ5yVV6H5NhnhyAkKK8uUiZOUUlUAk3HdV+4xg=="], + + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], + + "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], + + "p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="], + + "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], + + "p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="], + + "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + + "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "web-streams-polyfill": ["web-streams-polyfill@3.2.1", "", {}, "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "yaml": ["yaml@2.3.4", "", {}, "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA=="], + + "zod": ["zod@3.22.4", "", {}, "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg=="], + + "zod-to-json-schema": ["zod-to-json-schema@3.20.3", "", { "peerDependencies": { "zod": "^3.20.0" } }, "sha512-/Q3wnyxAfCt94ZcrGiXXoiAfRqasxl9CX64LZ9fj+4dKH68zulUtU0uk1WMxQPfAxQ0ZI70dKzcoW7hHj+DwSQ=="], + + "@types/node-fetch/@types/node": ["@types/node@20.9.0", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw=="], + + "formdata-node/web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="], + } +} +" +`; + +exports[`should not deduplicate bundled packages with un-bundled packages 1`] = ` +[ + "", + "+ debug-1@4.4.0", + "+ npm-1@10.9.2", + "", + "3 packages installed", +] +`; + +exports[`should not change formatting unexpectedly 1`] = ` +[ + "preinstall", + "", + "+ optional-native@1.0.0", + "+ optional-peer-deps@1.0.0 (v1.0.1 available)", + "+ uses-what-bin@1.0.0 (v1.5.0 available)", + "", + "13 packages installed", +] +`; + +exports[`should not change formatting unexpectedly 2`] = ` +"{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "pkg-root", + "dependencies": { + "uses-what-bin": "1.0.0", + }, + "devDependencies": { + "optional-peer-deps": "1.0.0", + }, + "optionalDependencies": { + "optional-native": "1.0.0", + }, + }, + "packages/pkg1": { + "name": "pkg1", + "version": "2.2.2", + "bin": { + "pkg1-1": "bin-1.js", + "pkg1-2": "bin-2.js", + "pkg1-3": "bin-3.js", + }, + "dependencies": { + "bundled-1": "1.0.0", + }, + "peerDependencies": { + "a-dep": "1.0.1", + }, + "optionalPeers": [ + "a-dep", + ], + }, + "packages/pkg2": { + "name": "pkg2", + "bin": { + "pkg2-1": "bin-1.js", + }, + "dependencies": { + "map-bin": "1.0.2", + }, + }, + "packages/pkg3": { + "name": "pkg3", + "binDir": "bin", + "devDependencies": { + "hoist-lockfile-1": "1.0.0", + }, + }, + }, + "trustedDependencies": [ + "uses-what-bin", + ], + "patchedDependencies": { + "optional-peer-deps@1.0.0": "patches/optional-peer-deps@1.0.0.patch", + }, + "overrides": { + "hoist-lockfile-shared": "1.0.1", + }, + "packages": { + "bundled-1": ["bundled-1@1.0.0", "http://localhost:1234/bundled-1/-/bundled-1-1.0.0.tgz", { "dependencies": { "no-deps": "1.0.0" } }, "sha512-YQ/maWZliKQyp1VIdYnPBH6qBHLCQ8Iy6G5vRZFXUHVXufiXT5aTjPVnLQ7xpVAgURFrzd/Fu1113ROLlaJBkQ=="], + + "hoist-lockfile-1": ["hoist-lockfile-1@1.0.0", "http://localhost:1234/hoist-lockfile-1/-/hoist-lockfile-1-1.0.0.tgz", { "dependencies": { "hoist-lockfile-shared": "*" } }, "sha512-E2nwR7egMFDoYjeRno7CAa59kiwkLGfhTFy2Q335JWp2r2bDkwoAt1LdChd5PdGYkbo7SfViHkW44ga+WXA+eA=="], + + "hoist-lockfile-shared": ["hoist-lockfile-shared@1.0.1", "http://localhost:1234/hoist-lockfile-shared/-/hoist-lockfile-shared-1.0.1.tgz", {}, "sha512-wPw8pTRj2OeZ/n7NeixjaSeI7FoM9DbMHWzdLv1kuBesSXJn+17UA0N7LV7t9dREnIMLw7ycRomhDL+56NRBmQ=="], + + "map-bin": ["map-bin@1.0.2", "http://localhost:1234/map-bin/-/map-bin-1.0.2.tgz", { "bin": { "map-bin": "bin/map-bin", "map_bin": "bin/map-bin" } }, "sha512-d5+2d5socrCT/99w16Gdl/wQu+C3WHflIE/3idFuJOW9xuvt+8VW4bDND/kptCNI63w/ePSJoYm327Sn+I7QCQ=="], + + "native-bar-x64": ["native-bar-x64@1.0.0", "http://localhost:1234/native-bar-x64/-/native-bar-x64-1.0.0.tgz", { "os": "none", "cpu": "x64" }, "sha512-wNjF++hO2mWgeg1uyFzyTUq1tWiO/1kEjKqvgf344NmKJ3JiUp58dSaes4b26AoUT/rrrHEU9SGUu550E9/sUA=="], + + "native-foo-x64": ["native-foo-x64@1.0.0", "http://localhost:1234/native-foo-x64/-/native-foo-x64-1.0.0.tgz", { "os": "none", "cpu": "x64" }, "sha512-+KlZNC/c4RF1wx4ZYdrr2ZfouSHMWM4YLT/yCfh97dlIW1JuRs9LnbdUwrsM007hVF0khUGM9TSVcx+elB6NpQ=="], + + "native-foo-x86": ["native-foo-x86@1.0.0", "http://localhost:1234/native-foo-x86/-/native-foo-x86-1.0.0.tgz", { "os": "none", "cpu": "none" }, "sha512-pUktFGar8JctgQh4Ow5Y9bMp3PB5bHBgbC6M3igED5q99z51WErG2GO3LnPG651SyHtRf+zdeMdhGFWzP54apQ=="], + + "native-libc-glibc": ["native-libc-glibc@1.0.0", "http://localhost:1234/native-libc-glibc/-/native-libc-glibc-1.0.0.tgz", {}, "sha512-D7ivPUqV+bs4jZCFt/fm0BRchhE1kO3XMKZ7/Tt3cF2gfJcewMy/zuId79iaVn9aztJYkOk1GWFpMPXmX5rJHA=="], + + "native-libc-musl": ["native-libc-musl@1.0.0", "http://localhost:1234/native-libc-musl/-/native-libc-musl-1.0.0.tgz", {}, "sha512-1uffg8IA4EJ4VUnuZU4zyRO9EyduuNfbqg2MMVCWSMAsQkfzZnNR0hqtL0GW/EuhE8FWU/FE//Srf1px1pnN2Q=="], + + "optional-native": ["optional-native@1.0.0", "http://localhost:1234/optional-native/-/optional-native-1.0.0.tgz", { "optionalDependencies": { "native-bar-x64": "1.0.0", "native-foo-x64": "1.0.0", "native-foo-x86": "1.0.0", "native-libc-glibc": "1.0.0", "native-libc-musl": "1.0.0" } }, "sha512-E+XTkTpxRqU09BnKGkOkS9vk0sPDhPtArBw6FfL5ciYkb7k6EljnqXEQ1b9l0S1YCVZxZkOZIJCYZfCwj7AgSw=="], + + "optional-peer-deps": ["optional-peer-deps@1.0.0", "http://localhost:1234/optional-peer-deps/-/optional-peer-deps-1.0.0.tgz", { "peerDependencies": { "no-deps": "*" }, "optionalPeers": ["no-deps"] }, "sha512-gJZ2WKSXFwQHjjYNxAjYYIwtgNvDnL+CKURXTtOKNDX27XZN0a9bt+cDgLcCVBTy0V/nQ8h6yW7a6fO34Lv22w=="], + + "pkg1": ["pkg1@workspace:packages/pkg1"], + + "pkg2": ["pkg2@workspace:packages/pkg2"], + + "pkg3": ["pkg3@workspace:packages/pkg3"], + + "uses-what-bin": ["uses-what-bin@1.0.0", "http://localhost:1234/uses-what-bin/-/uses-what-bin-1.0.0.tgz", { "dependencies": { "what-bin": "1.0.0" } }, "sha512-87/Emb1Hh7HtsMMU1yXXhI/+/5opQFbnqtR0Yq/1rgr7jp4mzkMU8wQBiYtS8C45GJY6YfdIqq1Dci+0ivJB2g=="], + + "what-bin": ["what-bin@1.0.0", "http://localhost:1234/what-bin/-/what-bin-1.0.0.tgz", { "bin": { "what-bin": "what-bin.js" } }, "sha512-sa99On1k5aDqCvpni/TQ6rLzYprUWBlb8fNwWOzbjDlM24fRr7FKDOuaBO/Y9WEIcZuzoPkCW5EkBCpflj8REQ=="], + + "bundled-1/no-deps": ["no-deps@1.0.0", "http://localhost:1234/no-deps/-/no-deps-1.0.0.tgz", { "bundled": true }, "sha512-v4w12JRjUGvfHDUP8vFDwu0gUWu04j0cv9hLb1Abf9VdaXu4XcrddYFTMVBVvmldKViGWH7jrb6xPJRF0wq6gw=="], + } +} +" +`; + +exports[`should not change formatting unexpectedly 3`] = ` +[ + "preinstall", + "", + "+ bundled-1@1.0.0", + "", + "13 packages installed", +] +`; diff --git a/test/cli/install/bun-install-registry.test.ts b/test/cli/install/bun-install-registry.test.ts index 1461b3a78a225e..499b6ac2615e83 100644 --- a/test/cli/install/bun-install-registry.test.ts +++ b/test/cli/install/bun-install-registry.test.ts @@ -742,38 +742,9 @@ ljelkjwelkgjw;lekj;lkejflkj }); }); -export async function publish( - env: any, - cwd: string, - ...args: string[] -): Promise<{ out: string; err: string; exitCode: number }> { - const { stdout, stderr, exited } = spawn({ - cmd: [bunExe(), "publish", ...args], - cwd, - stdout: "pipe", - stderr: "pipe", - env, - }); - - const out = await Bun.readableStreamToText(stdout); - const err = stderrForInstall(await Bun.readableStreamToText(stderr)); - const exitCode = await exited; - return { out, err, exitCode }; -} - -async function authBunfig(user: string) { - const authToken = await generateRegistryUser(user, user); - return ` - [install] - cache = false - registry = { url = "http://localhost:${port}/", token = "${authToken}" } - saveTextLockfile = false - `; -} - describe("whoami", async () => { test("can get username", async () => { - const bunfig = await authBunfig("whoami"); + const bunfig = await verdaccio.authBunfig("whoami"); await Promise.all([ write( packageJson, @@ -900,6 +871,7 @@ describe("whoami", async () => { [install] cache = false registry = { url = "http://localhost:${port}/", token = "1234567" }`; + await rm(join(packageDir, "bunfig.toml")); await Promise.all([ write(packageJson, JSON.stringify({ name: "whoami-pkg", version: "1.1.1" })), write(join(packageDir, "bunfig.toml"), bunfig), @@ -919,690 +891,6 @@ describe("whoami", async () => { }); }); -describe("publish", async () => { - describe("otp", async () => { - const mockRegistryFetch = function (opts: { - token: string; - setAuthHeader?: boolean; - otpFail?: boolean; - npmNotice?: boolean; - xLocalCache?: boolean; - expectedCI?: string; - }) { - return async function (req: Request) { - const { token, setAuthHeader = true, otpFail = false, npmNotice = false, xLocalCache = false } = opts; - if (req.url.includes("otp-pkg")) { - if (opts.expectedCI) { - expect(req.headers.get("user-agent")).toContain("ci/" + opts.expectedCI); - } - if (req.headers.get("npm-otp") === token) { - if (otpFail) { - return new Response( - JSON.stringify({ - error: "You must provide a one-time pass. Upgrade your client to npm@latest in order to use 2FA.", - }), - { status: 401 }, - ); - } else { - return new Response("OK", { status: 200 }); - } - } else { - const headers = new Headers(); - if (setAuthHeader) headers.set("www-authenticate", "OTP"); - - // `bun publish` won't request a url from a message in the npm-notice header, but we - // can test that it's displayed - if (npmNotice) headers.set("npm-notice", `visit http://localhost:${this.port}/auth to login`); - - // npm-notice will be ignored - if (xLocalCache) headers.set("x-local-cache", "true"); - - return new Response( - JSON.stringify({ - // this isn't accurate, but we just want to check that finding this string works - mock: setAuthHeader ? "" : "one-time password", - - authUrl: `http://localhost:${this.port}/auth`, - doneUrl: `http://localhost:${this.port}/done`, - }), - { - status: 401, - headers, - }, - ); - } - } else if (req.url.endsWith("auth")) { - expect.unreachable("url given to user, bun publish should not request"); - } else if (req.url.endsWith("done")) { - // send a fake response saying the user has authenticated successfully with the auth url - return new Response(JSON.stringify({ token: token }), { status: 200 }); - } - - expect.unreachable("unexpected url"); - }; - }; - - for (const setAuthHeader of [true, false]) { - test("mock web login" + (setAuthHeader ? "" : " (without auth header)"), async () => { - const token = await generateRegistryUser("otp" + (setAuthHeader ? "" : "noheader"), "otp"); - - using mockRegistry = Bun.serve({ - port: 0, - fetch: mockRegistryFetch({ token }), - }); - - const bunfig = ` - [install] - cache = false - registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; - await Promise.all([ - rm(join(verdaccio.packagesPath, "otp-pkg-1"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "otp-pkg-1", - version: "2.2.2", - dependencies: { - "otp-pkg-1": "2.2.2", - }, - }), - ), - ]); - - const { out, err, exitCode } = await publish(env, packageDir); - expect(exitCode).toBe(0); - }); - } - - test("otp failure", async () => { - const token = await generateRegistryUser("otp-fail", "otp"); - using mockRegistry = Bun.serve({ - port: 0, - fetch: mockRegistryFetch({ token, otpFail: true }), - }); - - const bunfig = ` - [install] - cache = false - registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; - - await Promise.all([ - rm(join(verdaccio.packagesPath, "otp-pkg-2"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "otp-pkg-2", - version: "1.1.1", - dependencies: { - "otp-pkg-2": "1.1.1", - }, - }), - ), - ]); - - const { out, err, exitCode } = await publish(env, packageDir); - expect(exitCode).toBe(1); - expect(err).toContain(" - Received invalid OTP"); - }); - - for (const shouldIgnoreNotice of [false, true]) { - test(`npm-notice with login url${shouldIgnoreNotice ? " (ignored)" : ""}`, async () => { - // Situation: user has 2FA enabled account with faceid sign-in. - // They run `bun publish` with --auth-type=legacy, prompting them - // to enter their OTP. Because they have faceid sign-in, they don't - // have a code to enter, so npm sends a message in the npm-notice - // header with a url for logging in. - const token = await generateRegistryUser(`otp-notice${shouldIgnoreNotice ? "-ignore" : ""}`, "otp"); - using mockRegistry = Bun.serve({ - port: 0, - fetch: mockRegistryFetch({ token, npmNotice: true, xLocalCache: shouldIgnoreNotice }), - }); - - const bunfig = ` - [install] - cache = false - registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; - - await Promise.all([ - rm(join(verdaccio.packagesPath, "otp-pkg-3"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "otp-pkg-3", - version: "3.3.3", - dependencies: { - "otp-pkg-3": "3.3.3", - }, - }), - ), - ]); - - const { out, err, exitCode } = await publish(env, packageDir); - expect(exitCode).toBe(0); - if (shouldIgnoreNotice) { - expect(err).not.toContain(`note: visit http://localhost:${mockRegistry.port}/auth to login`); - } else { - expect(err).toContain(`note: visit http://localhost:${mockRegistry.port}/auth to login`); - } - }); - } - - const fakeCIEnvs = [ - { ci: "expo-application-services", envs: { EAS_BUILD: "hi" } }, - { ci: "codemagic", envs: { CM_BUILD_ID: "hi" } }, - { ci: "vercel", envs: { "NOW_BUILDER": "hi" } }, - ]; - for (const envInfo of fakeCIEnvs) { - test(`CI user agent name: ${envInfo.ci}`, async () => { - const token = await generateRegistryUser(`otp-${envInfo.ci}`, "otp"); - using mockRegistry = Bun.serve({ - port: 0, - fetch: mockRegistryFetch({ token, expectedCI: envInfo.ci }), - }); - - const bunfig = ` - [install] - cache = false - registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; - - await Promise.all([ - rm(join(verdaccio.packagesPath, "otp-pkg-4"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "otp-pkg-4", - version: "4.4.4", - dependencies: { - "otp-pkg-4": "4.4.4", - }, - }), - ), - ]); - - const { out, err, exitCode } = await publish( - { ...env, ...envInfo.envs, ...{ BUILDKITE: undefined, GITHUB_ACTIONS: undefined } }, - packageDir, - ); - expect(exitCode).toBe(0); - }); - } - }); - - test("can publish a package then install it", async () => { - const bunfig = await authBunfig("basic"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-1"), { recursive: true, force: true }), - write( - packageJson, - JSON.stringify({ - name: "publish-pkg-1", - version: "1.1.1", - dependencies: { - "publish-pkg-1": "1.1.1", - }, - }), - ), - write(join(packageDir, "bunfig.toml"), bunfig), - ]); - - const { out, err, exitCode } = await publish(env, packageDir); - expect(err).not.toContain("error:"); - expect(err).not.toContain("warn:"); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - expect(await exists(join(packageDir, "node_modules", "publish-pkg-1", "package.json"))).toBeTrue(); - }); - test("can publish from a tarball", async () => { - const bunfig = await authBunfig("tarball"); - const json = { - name: "publish-pkg-2", - version: "2.2.2", - dependencies: { - "publish-pkg-2": "2.2.2", - }, - }; - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-2"), { recursive: true, force: true }), - write(packageJson, JSON.stringify(json)), - write(join(packageDir, "bunfig.toml"), bunfig), - ]); - - await pack(packageDir, env); - - let { out, err, exitCode } = await publish(env, packageDir, "./publish-pkg-2-2.2.2.tgz"); - expect(err).not.toContain("error:"); - expect(err).not.toContain("warn:"); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - expect(await exists(join(packageDir, "node_modules", "publish-pkg-2", "package.json"))).toBeTrue(); - - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-2"), { recursive: true, force: true }), - rm(join(packageDir, "bun.lockb"), { recursive: true, force: true }), - rm(join(packageDir, "node_modules"), { recursive: true, force: true }), - ]); - - // now with an absoute path - ({ out, err, exitCode } = await publish(env, packageDir, join(packageDir, "publish-pkg-2-2.2.2.tgz"))); - expect(err).not.toContain("error:"); - expect(err).not.toContain("warn:"); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - expect(await file(join(packageDir, "node_modules", "publish-pkg-2", "package.json")).json()).toEqual(json); - }); - - for (const info of [ - { user: "bin1", bin: "bin1.js" }, - { user: "bin2", bin: { bin1: "bin1.js", bin2: "bin2.js" } }, - { user: "bin3", directories: { bin: "bins" } }, - ]) { - test(`can publish and install binaries with ${JSON.stringify(info)}`, async () => { - const publishDir = tmpdirSync(); - const bunfig = await authBunfig("binaries-" + info.user); - console.log({ packageDir, publishDir }); - - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-bins"), { recursive: true, force: true }), - write( - join(publishDir, "package.json"), - JSON.stringify({ - name: "publish-pkg-bins", - version: "1.1.1", - ...info, - }), - ), - write(join(publishDir, "bunfig.toml"), bunfig), - write(join(publishDir, "bin1.js"), `#!/usr/bin/env bun\nconsole.log("bin1!")`), - write(join(publishDir, "bin2.js"), `#!/usr/bin/env bun\nconsole.log("bin2!")`), - write(join(publishDir, "bins", "bin3.js"), `#!/usr/bin/env bun\nconsole.log("bin3!")`), - write(join(publishDir, "bins", "moredir", "bin4.js"), `#!/usr/bin/env bun\nconsole.log("bin4!")`), - - write( - packageJson, - JSON.stringify({ - name: "foo", - dependencies: { - "publish-pkg-bins": "1.1.1", - }, - }), - ), - ]); - - const { out, err, exitCode } = await publish(env, publishDir); - expect(err).not.toContain("error:"); - expect(err).not.toContain("warn:"); - expect(out).toContain("+ publish-pkg-bins@1.1.1"); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - - const results = await Promise.all([ - exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin1.bunx" : "bin1")), - exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin2.bunx" : "bin2")), - exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin3.js.bunx" : "bin3.js")), - exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin4.js.bunx" : "bin4.js")), - exists(join(packageDir, "node_modules", ".bin", isWindows ? "moredir" : "moredir/bin4.js")), - exists(join(packageDir, "node_modules", ".bin", isWindows ? "publish-pkg-bins.bunx" : "publish-pkg-bins")), - ]); - - switch (info.user) { - case "bin1": { - expect(results).toEqual([false, false, false, false, false, true]); - break; - } - case "bin2": { - expect(results).toEqual([true, true, false, false, false, false]); - break; - } - case "bin3": { - expect(results).toEqual([false, false, true, true, !isWindows, false]); - break; - } - } - }); - } - - test("dependencies are installed", async () => { - const publishDir = tmpdirSync(); - const bunfig = await authBunfig("manydeps"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-deps"), { recursive: true, force: true }), - write( - join(publishDir, "package.json"), - JSON.stringify( - { - name: "publish-pkg-deps", - version: "1.1.1", - dependencies: { - "no-deps": "1.0.0", - }, - peerDependencies: { - "a-dep": "1.0.1", - }, - optionalDependencies: { - "basic-1": "1.0.0", - }, - }, - null, - 2, - ), - ), - write(join(publishDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "foo", - dependencies: { - "publish-pkg-deps": "1.1.1", - }, - }), - ), - ]); - - let { out, err, exitCode } = await publish(env, publishDir); - expect(err).not.toContain("error:"); - expect(err).not.toContain("warn:"); - expect(out).toContain("+ publish-pkg-deps@1.1.1"); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - - const results = await Promise.all([ - exists(join(packageDir, "node_modules", "no-deps", "package.json")), - exists(join(packageDir, "node_modules", "a-dep", "package.json")), - exists(join(packageDir, "node_modules", "basic-1", "package.json")), - ]); - - expect(results).toEqual([true, true, true]); - }); - - test("can publish workspace package", async () => { - const bunfig = await authBunfig("workspace"); - const pkgJson = { - name: "publish-pkg-3", - version: "3.3.3", - dependencies: { - "publish-pkg-3": "3.3.3", - }, - }; - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-3"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "root", - workspaces: ["packages/*"], - }), - ), - write(join(packageDir, "packages", "publish-pkg-3", "package.json"), JSON.stringify(pkgJson)), - ]); - - await publish(env, join(packageDir, "packages", "publish-pkg-3")); - - await write(packageJson, JSON.stringify({ name: "root", "dependencies": { "publish-pkg-3": "3.3.3" } })); - - await runBunInstall(env, packageDir); - - expect(await file(join(packageDir, "node_modules", "publish-pkg-3", "package.json")).json()).toEqual(pkgJson); - }); - - describe("--dry-run", async () => { - test("does not publish", async () => { - const bunfig = await authBunfig("dryrun"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "dry-run-1"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "dry-run-1", - version: "1.1.1", - dependencies: { - "dry-run-1": "1.1.1", - }, - }), - ), - ]); - - const { out, err, exitCode } = await publish(env, packageDir, "--dry-run"); - expect(exitCode).toBe(0); - - expect(await exists(join(verdaccio.packagesPath, "dry-run-1"))).toBeFalse(); - }); - test("does not publish from tarball path", async () => { - const bunfig = await authBunfig("dryruntarball"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "dry-run-2"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "dry-run-2", - version: "2.2.2", - dependencies: { - "dry-run-2": "2.2.2", - }, - }), - ), - ]); - - await pack(packageDir, env); - - const { out, err, exitCode } = await publish(env, packageDir, "./dry-run-2-2.2.2.tgz", "--dry-run"); - expect(exitCode).toBe(0); - - expect(await exists(join(verdaccio.packagesPath, "dry-run-2"))).toBeFalse(); - }); - }); - - describe("lifecycle scripts", async () => { - const script = `const fs = require("fs"); - fs.writeFileSync(process.argv[2] + ".txt", \` -prepublishOnly: \${fs.existsSync("prepublishOnly.txt")} -publish: \${fs.existsSync("publish.txt")} -postpublish: \${fs.existsSync("postpublish.txt")} -prepack: \${fs.existsSync("prepack.txt")} -prepare: \${fs.existsSync("prepare.txt")} -postpack: \${fs.existsSync("postpack.txt")}\`)`; - const json = { - name: "publish-pkg-4", - version: "4.4.4", - scripts: { - // should happen in this order - "prepublishOnly": `${bunExe()} script.js prepublishOnly`, - "prepack": `${bunExe()} script.js prepack`, - "prepare": `${bunExe()} script.js prepare`, - "postpack": `${bunExe()} script.js postpack`, - "publish": `${bunExe()} script.js publish`, - "postpublish": `${bunExe()} script.js postpublish`, - }, - dependencies: { - "publish-pkg-4": "4.4.4", - }, - }; - - for (const arg of ["", "--dry-run"]) { - test(`should run in order${arg ? " (--dry-run)" : ""}`, async () => { - const bunfig = await authBunfig("lifecycle" + (arg ? "dry" : "")); - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-4"), { recursive: true, force: true }), - write(packageJson, JSON.stringify(json)), - write(join(packageDir, "script.js"), script), - write(join(packageDir, "bunfig.toml"), bunfig), - ]); - - const { out, err, exitCode } = await publish(env, packageDir, arg); - expect(exitCode).toBe(0); - - const results = await Promise.all([ - file(join(packageDir, "prepublishOnly.txt")).text(), - file(join(packageDir, "prepack.txt")).text(), - file(join(packageDir, "prepare.txt")).text(), - file(join(packageDir, "postpack.txt")).text(), - file(join(packageDir, "publish.txt")).text(), - file(join(packageDir, "postpublish.txt")).text(), - ]); - - expect(results).toEqual([ - "\nprepublishOnly: false\npublish: false\npostpublish: false\nprepack: false\nprepare: false\npostpack: false", - "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: false\nprepare: false\npostpack: false", - "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: true\nprepare: false\npostpack: false", - "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: true\nprepare: true\npostpack: false", - "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: true\nprepare: true\npostpack: true", - "\nprepublishOnly: true\npublish: true\npostpublish: false\nprepack: true\nprepare: true\npostpack: true", - ]); - }); - } - - test("--ignore-scripts", async () => { - const bunfig = await authBunfig("ignorescripts"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-5"), { recursive: true, force: true }), - write(packageJson, JSON.stringify(json)), - write(join(packageDir, "script.js"), script), - write(join(packageDir, "bunfig.toml"), bunfig), - ]); - - const { out, err, exitCode } = await publish(env, packageDir, "--ignore-scripts"); - expect(exitCode).toBe(0); - - const results = await Promise.all([ - exists(join(packageDir, "prepublishOnly.txt")), - exists(join(packageDir, "prepack.txt")), - exists(join(packageDir, "prepare.txt")), - exists(join(packageDir, "postpack.txt")), - exists(join(packageDir, "publish.txt")), - exists(join(packageDir, "postpublish.txt")), - ]); - - expect(results).toEqual([false, false, false, false, false, false]); - }); - }); - - test("attempting to publish a private package should fail", async () => { - const bunfig = await authBunfig("privatepackage"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-6"), { recursive: true, force: true }), - write( - packageJson, - JSON.stringify({ - name: "publish-pkg-6", - version: "6.6.6", - private: true, - dependencies: { - "publish-pkg-6": "6.6.6", - }, - }), - ), - write(join(packageDir, "bunfig.toml"), bunfig), - ]); - - // should fail - let { out, err, exitCode } = await publish(env, packageDir); - expect(exitCode).toBe(1); - expect(err).toContain("error: attempted to publish a private package"); - expect(await exists(join(verdaccio.packagesPath, "publish-pkg-6-6.6.6.tgz"))).toBeFalse(); - - // try tarball - await pack(packageDir, env); - ({ out, err, exitCode } = await publish(env, packageDir, "./publish-pkg-6-6.6.6.tgz")); - expect(exitCode).toBe(1); - expect(err).toContain("error: attempted to publish a private package"); - expect(await exists(join(packageDir, "publish-pkg-6-6.6.6.tgz"))).toBeTrue(); - }); - - describe("access", async () => { - test("--access", async () => { - const bunfig = await authBunfig("accessflag"); - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-7"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write( - packageJson, - JSON.stringify({ - name: "publish-pkg-7", - version: "7.7.7", - }), - ), - ]); - - // should fail - let { out, err, exitCode } = await publish(env, packageDir, "--access", "restricted"); - expect(exitCode).toBe(1); - expect(err).toContain("error: unable to restrict access to unscoped package"); - - ({ out, err, exitCode } = await publish(env, packageDir, "--access", "public")); - expect(exitCode).toBe(0); - - expect(await exists(join(verdaccio.packagesPath, "publish-pkg-7"))).toBeTrue(); - }); - - for (const access of ["restricted", "public"]) { - test(`access ${access}`, async () => { - const bunfig = await authBunfig("access" + access); - - const pkgJson = { - name: "@secret/publish-pkg-8", - version: "8.8.8", - dependencies: { - "@secret/publish-pkg-8": "8.8.8", - }, - publishConfig: { - access, - }, - }; - - await Promise.all([ - rm(join(verdaccio.packagesPath, "@secret", "publish-pkg-8"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write(packageJson, JSON.stringify(pkgJson)), - ]); - - let { out, err, exitCode } = await publish(env, packageDir); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - - expect(await file(join(packageDir, "node_modules", "@secret", "publish-pkg-8", "package.json")).json()).toEqual( - pkgJson, - ); - }); - } - }); - - describe("tag", async () => { - test("can publish with a tag", async () => { - const bunfig = await authBunfig("simpletag"); - const pkgJson = { - name: "publish-pkg-9", - version: "9.9.9", - dependencies: { - "publish-pkg-9": "simpletag", - }, - }; - await Promise.all([ - rm(join(verdaccio.packagesPath, "publish-pkg-9"), { recursive: true, force: true }), - write(join(packageDir, "bunfig.toml"), bunfig), - write(packageJson, JSON.stringify(pkgJson)), - ]); - - let { out, err, exitCode } = await publish(env, packageDir, "--tag", "simpletag"); - expect(exitCode).toBe(0); - - await runBunInstall(env, packageDir); - expect(await file(join(packageDir, "node_modules", "publish-pkg-9", "package.json")).json()).toEqual(pkgJson); - }); - }); -}); - describe("package.json indentation", async () => { test("works for root and workspace packages", async () => { await Promise.all([ @@ -5367,7 +4655,7 @@ describe("hoisting", async () => { }); }); -describe.only("transitive file dependencies", () => { +describe("transitive file dependencies", () => { async function checkHoistedFiles() { const aliasedFileDepFilesPackageJson = join( packageDir, @@ -5379,28 +4667,36 @@ describe.only("transitive file dependencies", () => { "package.json", ); const results = await Promise.all([ - (await lstat(join(packageDir, "node_modules", "file-dep", "node_modules", "files", "package.json"))).isSymbolicLink(), + ( + await lstat(join(packageDir, "node_modules", "file-dep", "node_modules", "files", "package.json")) + ).isSymbolicLink(), readdirSorted(join(packageDir, "node_modules", "missing-file-dep", "node_modules")), exists(join(packageDir, "node_modules", "aliased-file-dep", "package.json")), isWindows ? file(await readlink(aliasedFileDepFilesPackageJson)).json() : file(aliasedFileDepFilesPackageJson).json(), - (await lstat( - join(packageDir, "node_modules", "@scoped", "file-dep", "node_modules", "@scoped", "files", "package.json"), - )).isSymbolicLink(), - (await lstat( - join( - packageDir, - "node_modules", - "@another-scope", - "file-dep", - "node_modules", - "@scoped", - "files", - "package.json", - ), - )).isSymbolicLink(), - (await lstat(join(packageDir, "node_modules", "self-file-dep", "node_modules", "self-file-dep", "package.json"))).isSymbolicLink(), + ( + await lstat( + join(packageDir, "node_modules", "@scoped", "file-dep", "node_modules", "@scoped", "files", "package.json"), + ) + ).isSymbolicLink(), + ( + await lstat( + join( + packageDir, + "node_modules", + "@another-scope", + "file-dep", + "node_modules", + "@scoped", + "files", + "package.json", + ), + ) + ).isSymbolicLink(), + ( + await lstat(join(packageDir, "node_modules", "self-file-dep", "node_modules", "self-file-dep", "package.json")) + ).isSymbolicLink(), ]); expect(results).toEqual([ @@ -5430,38 +4726,46 @@ describe.only("transitive file dependencies", () => { file(join(packageDir, "node_modules", "@another-scope", "file-dep", "package.json")).json(), file(join(packageDir, "node_modules", "self-file-dep", "package.json")).json(), - (await lstat(join(packageDir, "pkg1", "node_modules", "file-dep", "node_modules", "files", "package.json"))).isSymbolicLink(), + ( + await lstat(join(packageDir, "pkg1", "node_modules", "file-dep", "node_modules", "files", "package.json")) + ).isSymbolicLink(), readdirSorted(join(packageDir, "pkg1", "node_modules", "missing-file-dep", "node_modules")), // [] exists(join(packageDir, "pkg1", "node_modules", "aliased-file-dep")), // false - (await lstat( - join( - packageDir, - "pkg1", - "node_modules", - "@scoped", - "file-dep", - "node_modules", - "@scoped", - "files", - "package.json", - ), - )).isSymbolicLink(), - (await lstat( - join( - packageDir, - "pkg1", - "node_modules", - "@another-scope", - "file-dep", - "node_modules", - "@scoped", - "files", - "package.json", - ), - )).isSymbolicLink(), - (await lstat( - join(packageDir, "pkg1", "node_modules", "self-file-dep", "node_modules", "self-file-dep", "package.json"), - )).isSymbolicLink(), + ( + await lstat( + join( + packageDir, + "pkg1", + "node_modules", + "@scoped", + "file-dep", + "node_modules", + "@scoped", + "files", + "package.json", + ), + ) + ).isSymbolicLink(), + ( + await lstat( + join( + packageDir, + "pkg1", + "node_modules", + "@another-scope", + "file-dep", + "node_modules", + "@scoped", + "files", + "package.json", + ), + ) + ).isSymbolicLink(), + ( + await lstat( + join(packageDir, "pkg1", "node_modules", "self-file-dep", "node_modules", "self-file-dep", "package.json"), + ) + ).isSymbolicLink(), readdirSorted(join(packageDir, "pkg1", "node_modules")), ]); @@ -9683,79 +8987,3 @@ registry = "http://localhost:${port}/" }); } }); - -it("$npm_command is accurate during publish", async () => { - await write( - packageJson, - JSON.stringify({ - name: "publish-pkg-10", - version: "1.0.0", - scripts: { - publish: "echo $npm_command", - }, - }), - ); - await write(join(packageDir, "bunfig.toml"), await authBunfig("npm_command")); - await rm(join(verdaccio.packagesPath, "publish-pkg-10"), { recursive: true, force: true }); - let { out, err, exitCode } = await publish(env, packageDir, "--tag", "simpletag"); - expect(err).toBe(`$ echo $npm_command\n`); - expect(out.split("\n")).toEqual([ - `bun publish ${Bun.version_with_sha}`, - ``, - `packed 95B package.json`, - ``, - `Total files: 1`, - expect.stringContaining(`Shasum: `), - expect.stringContaining(`Integrity: sha512-`), - `Unpacked size: 95B`, - expect.stringContaining(`Packed size: `), - `Tag: simpletag`, - `Access: default`, - `Registry: http://localhost:${port}/`, - ``, - ` + publish-pkg-10@1.0.0`, - `publish`, - ``, - ]); - expect(exitCode).toBe(0); -}); - -it("$npm_lifecycle_event is accurate during publish", async () => { - await write( - packageJson, - `{ - "name": "publish-pkg-11", - "version": "1.0.0", - "scripts": { - "prepublish": "echo 1 $npm_lifecycle_event", - "publish": "echo 2 $npm_lifecycle_event", - "postpublish": "echo 3 $npm_lifecycle_event", - }, - } - `, - ); - await write(join(packageDir, "bunfig.toml"), await authBunfig("npm_lifecycle_event")); - await rm(join(verdaccio.packagesPath, "publish-pkg-11"), { recursive: true, force: true }); - let { out, err, exitCode } = await publish(env, packageDir, "--tag", "simpletag"); - expect(err).toBe(`$ echo 2 $npm_lifecycle_event\n$ echo 3 $npm_lifecycle_event\n`); - expect(out.split("\n")).toEqual([ - `bun publish ${Bun.version_with_sha}`, - ``, - `packed 256B package.json`, - ``, - `Total files: 1`, - expect.stringContaining(`Shasum: `), - expect.stringContaining(`Integrity: sha512-`), - `Unpacked size: 256B`, - expect.stringContaining(`Packed size: `), - `Tag: simpletag`, - `Access: default`, - `Registry: http://localhost:${port}/`, - ``, - ` + publish-pkg-11@1.0.0`, - `2 publish`, - `3 postpublish`, - ``, - ]); - expect(exitCode).toBe(0); -}); diff --git a/test/cli/install/bun-lock.test.ts b/test/cli/install/bun-lock.test.ts index 5b43b47e50f20f..b636435ae97472 100644 --- a/test/cli/install/bun-lock.test.ts +++ b/test/cli/install/bun-lock.test.ts @@ -1,9 +1,13 @@ import { spawn, write, file } from "bun"; import { expect, it, beforeAll, afterAll } from "bun:test"; -import { access, copyFile, open, writeFile, exists } from "fs/promises"; -import { bunExe, bunEnv as env, isWindows, VerdaccioRegistry, runBunInstall } from "harness"; +import { access, copyFile, open, writeFile, exists, cp, rm } from "fs/promises"; +import { bunExe, bunEnv as env, isWindows, VerdaccioRegistry, runBunInstall, toBeValidBin } from "harness"; import { join } from "path"; +expect.extend({ + toBeValidBin, +}); + var registry = new VerdaccioRegistry(); beforeAll(async () => { @@ -155,3 +159,293 @@ it("should save the lockfile if --save-text-lockfile and --frozen-lockfile are u expect(firstLockfile).not.toBe(secondLockfile); expect(secondLockfile).toMatchSnapshot(); }); + +it("should convert a binary lockfile with invalid optional peers", async () => { + const { packageDir, packageJson } = await registry.createTestDir({ npm: true }); + await Promise.all([ + write( + packageJson, + JSON.stringify({ + name: "pkg1", + dependencies: { + "langchain": "^0.0.194", + }, + }), + ), + cp(join(import.meta.dir, "fixtures", "invalid-optional-peer.lockb"), join(packageDir, "bun.lockb")), + ]); + + let { exited, stdout, stderr } = spawn({ + cmd: [bunExe(), "install", "--save-text-lockfile", "--lockfile-only"], + cwd: packageDir, + env, + stdout: "pipe", + stderr: "pipe", + }); + + let [out, err] = await Promise.all([Bun.readableStreamToText(stdout), Bun.readableStreamToText(stderr)]); + expect(err).toContain("Saved lockfile"); + expect(out).toContain("Saved bun.lock (69 packages)"); + + expect(await exited).toBe(0); + + const [firstLockfile, lockbExists] = await Promise.all([ + await file(join(packageDir, "bun.lock")).text(), + exists(join(packageDir, "bun.lockb")), + ]); + + expect(firstLockfile).toMatchSnapshot(); + expect(lockbExists).toBeFalse(); + + // running again should not change the lockfile + ({ exited, stdout, stderr } = spawn({ + cmd: [bunExe(), "install", "--lockfile-only"], + cwd: packageDir, + env, + stdout: "pipe", + stderr: "pipe", + })); + + [out, err] = await Promise.all([Bun.readableStreamToText(stdout), Bun.readableStreamToText(stderr)]); + expect(err).toContain("Saved lockfile"); + expect(out).toContain("Saved bun.lock (69 packages)"); + + expect(await exited).toBe(0); + expect(await file(join(packageDir, "bun.lock")).text()).toBe(firstLockfile); +}); + +it("should not deduplicate bundled packages with un-bundled packages", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + + await Promise.all([ + write( + packageJson, + JSON.stringify({ + name: "bundled-deps", + dependencies: { + "debug-1": "4.4.0", + "npm-1": "10.9.2", + }, + }), + ), + ]); + + let { exited, stdout } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + env, + stdout: "pipe", + stderr: "inherit", + }); + + expect(await exited).toBe(0); + + async function checkModules() { + const res = await Promise.all([ + exists(join(packageDir, "node_modules/debug-1")), + exists(join(packageDir, "node_modules/npm-1")), + exists(join(packageDir, "node_modules/ms-1")), + ]); + expect(res).toEqual([true, true, true]); + } + + await checkModules(); + + const out1 = (await Bun.readableStreamToText(stdout)) + .replaceAll(/\s*\[[0-9\.]+m?s\]\s*$/g, "") + .split(/\r?\n/) + .slice(1); + expect(out1).toMatchSnapshot(); + + await rm(join(packageDir, "node_modules"), { recursive: true, force: true }); + + // running install again will install all packages to node_modules + ({ exited, stdout } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + env, + stdout: "pipe", + stderr: "inherit", + })); + + expect(await exited).toBe(0); + + await checkModules(); + const out2 = (await Bun.readableStreamToText(stdout)) + .replaceAll(/\s*\[[0-9\.]+m?s\]\s*$/g, "") + .split(/\r?\n/) + .slice(1); + expect(out2).toEqual(out1); +}); + +it("should not change formatting unexpectedly", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + + const patch = `diff --git a/package.json b/package.json +index d156130662798530e852e1afaec5b1c03d429cdc..b4ddf35975a952fdaed99f2b14236519694f850d 100644 +--- a/package.json ++++ b/package.json +@@ -1,6 +1,7 @@ + { + "name": "optional-peer-deps", + "version": "1.0.0", ++ "hi": true, + "peerDependencies": { + "no-deps": "*" + }, +`; + + // attempt to snapshot most things that can be printed + await Promise.all([ + write( + packageJson, + JSON.stringify({ + name: "pkg-root", + version: "1.0.0", + workspaces: ["packages/*"], + scripts: { + preinstall: "echo 'preinstall'", + }, + overrides: { + "hoist-lockfile-shared": "1.0.1", + }, + bin: "index.js", + optionalDependencies: { + "optional-native": "1.0.0", + }, + devDependencies: { + "optional-peer-deps": "1.0.0", + }, + dependencies: { + "uses-what-bin": "1.0.0", + }, + trustedDependencies: ["uses-what-bin"], + patchedDependencies: { + "optional-peer-deps@1.0.0": "patches/optional-peer-deps@1.0.0.patch", + }, + }), + ), + write(join(packageDir, "patches", "optional-peer-deps@1.0.0.patch"), patch), + write(join(packageDir, "index.js"), "console.log('hello world')"), + write( + join(packageDir, "packages", "pkg1", "package.json"), + JSON.stringify({ + name: "pkg1", + version: "2.2.2", + peerDependenciesMeta: { + "a-dep": { + optional: true, + }, + }, + peerDependencies: { + "a-dep": "1.0.1", + }, + dependencies: { + "bundled-1": "1.0.0", + }, + bin: { + "pkg1-1": "bin-1.js", + "pkg1-2": "bin-2.js", + "pkg1-3": "bin-3.js", + }, + scripts: { + install: "echo 'install'", + postinstall: "echo 'postinstall'", + }, + }), + ), + write(join(packageDir, "packages", "pkg1", "bin-1.js"), "console.log('bin-1')"), + write(join(packageDir, "packages", "pkg1", "bin-2.js"), "console.log('bin-2')"), + write(join(packageDir, "packages", "pkg1", "bin-3.js"), "console.log('bin-3')"), + write( + join(packageDir, "packages", "pkg2", "package.json"), + JSON.stringify({ + name: "pkg2", + bin: { + "pkg2-1": "bin-1.js", + }, + dependencies: { + "map-bin": "1.0.2", + }, + }), + ), + write(join(packageDir, "packages", "pkg2", "bin-1.js"), "console.log('bin-1')"), + write( + join(packageDir, "packages", "pkg3", "package.json"), + JSON.stringify({ + name: "pkg3", + directories: { + bin: "bin", + }, + devDependencies: { + "hoist-lockfile-1": "1.0.0", + }, + }), + ), + write(join(packageDir, "packages", "pkg3", "bin", "bin-1.js"), "console.log('bin-1')"), + ]); + + async function checkInstall() { + expect( + await Promise.all([ + exists(join(packageDir, "node_modules", "pkg1", "package.json")), + exists(join(packageDir, "node_modules", "pkg2", "package.json")), + exists(join(packageDir, "node_modules", "pkg3", "package.json")), + file(join(packageDir, "node_modules", "hoist-lockfile-shared", "package.json")).json(), + exists(join(packageDir, "node_modules", "uses-what-bin", "what-bin.txt")), + file(join(packageDir, "node_modules", "optional-peer-deps", "package.json")).json(), + ]), + ).toMatchObject([true, true, true, { name: "hoist-lockfile-shared", version: "1.0.1" }, true, { hi: true }]); + expect(join(packageDir, "node_modules", ".bin", "bin-1.js")).toBeValidBin(join("..", "pkg3", "bin", "bin-1.js")); + expect(join(packageDir, "node_modules", ".bin", "map-bin")).toBeValidBin(join("..", "map-bin", "bin", "map-bin")); + expect(join(packageDir, "node_modules", ".bin", "map_bin")).toBeValidBin(join("..", "map-bin", "bin", "map-bin")); + expect(join(packageDir, "node_modules", ".bin", "pkg1-1")).toBeValidBin(join("..", "pkg1", "bin-1.js")); + expect(join(packageDir, "node_modules", ".bin", "pkg1-2")).toBeValidBin(join("..", "pkg1", "bin-2.js")); + expect(join(packageDir, "node_modules", ".bin", "pkg1-3")).toBeValidBin(join("..", "pkg1", "bin-3.js")); + expect(join(packageDir, "node_modules", ".bin", "pkg2-1")).toBeValidBin(join("..", "pkg2", "bin-1.js")); + expect(join(packageDir, "node_modules", ".bin", "what-bin")).toBeValidBin(join("..", "what-bin", "what-bin.js")); + } + + let { exited, stdout } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + env, + stdout: "pipe", + stderr: "inherit", + }); + + expect(await exited).toBe(0); + const out1 = (await Bun.readableStreamToText(stdout)) + .replaceAll(/\s*\[[0-9\.]+m?s\]\s*$/g, "") + .split(/\r?\n/) + .slice(1); + expect(out1).toMatchSnapshot(); + + await checkInstall(); + + const lockfile = (await file(join(packageDir, "bun.lock")).text()).replaceAll(/localhost:\d+/g, "localhost:1234"); + expect(lockfile).toMatchSnapshot(); + + await rm(join(packageDir, "node_modules"), { recursive: true, force: true }); + + ({ exited, stdout } = spawn({ + cmd: [bunExe(), "install"], + cwd: join(packageDir, "packages", "pkg1"), + env, + stdout: "pipe", + stderr: "inherit", + })); + + expect(await exited).toBe(0); + const out2 = (await Bun.readableStreamToText(stdout)) + .replaceAll(/\s*\[[0-9\.]+m?s\]\s*$/g, "") + .split(/\r?\n/) + .slice(1); + expect(out2).toMatchSnapshot(); + + await checkInstall(); + + expect((await file(join(packageDir, "bun.lock")).text()).replaceAll(/localhost:\d+/g, "localhost:1234")).toBe( + lockfile, + ); +}); diff --git a/test/cli/install/bun-publish.test.ts b/test/cli/install/bun-publish.test.ts new file mode 100644 index 00000000000000..0141b078f60563 --- /dev/null +++ b/test/cli/install/bun-publish.test.ts @@ -0,0 +1,850 @@ +import { describe, expect, test, beforeAll, afterAll, it } from "bun:test"; +import { spawn, file, write } from "bun"; +import { rm, exists } from "fs/promises"; +import { join } from "path"; +import { + VerdaccioRegistry, + bunExe, + bunEnv as env, + stderrForInstall, + runBunInstall, + pack, + tmpdirSync, + isWindows, +} from "harness"; + +const registry = new VerdaccioRegistry(); + +beforeAll(async () => { + await registry.start(); +}); + +afterAll(() => { + registry.stop(); +}); + +export async function publish( + env: any, + cwd: string, + ...args: string[] +): Promise<{ out: string; err: string; exitCode: number }> { + const { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "publish", ...args], + cwd, + stdout: "pipe", + stderr: "pipe", + env, + }); + + const out = await Bun.readableStreamToText(stdout); + const err = stderrForInstall(await Bun.readableStreamToText(stderr)); + const exitCode = await exited; + return { out, err, exitCode }; +} + +describe("otp", async () => { + const mockRegistryFetch = function (opts: { + token: string; + setAuthHeader?: boolean; + otpFail?: boolean; + npmNotice?: boolean; + xLocalCache?: boolean; + expectedCI?: string; + }) { + return async function (req: Request) { + const { token, setAuthHeader = true, otpFail = false, npmNotice = false, xLocalCache = false } = opts; + if (req.url.includes("otp-pkg")) { + if (opts.expectedCI) { + expect(req.headers.get("user-agent")).toContain("ci/" + opts.expectedCI); + } + if (req.headers.get("npm-otp") === token) { + if (otpFail) { + return new Response( + JSON.stringify({ + error: "You must provide a one-time pass. Upgrade your client to npm@latest in order to use 2FA.", + }), + { status: 401 }, + ); + } else { + return new Response("OK", { status: 200 }); + } + } else { + const headers = new Headers(); + if (setAuthHeader) headers.set("www-authenticate", "OTP"); + + // `bun publish` won't request a url from a message in the npm-notice header, but we + // can test that it's displayed + if (npmNotice) headers.set("npm-notice", `visit http://localhost:${this.port}/auth to login`); + + // npm-notice will be ignored + if (xLocalCache) headers.set("x-local-cache", "true"); + + return new Response( + JSON.stringify({ + // this isn't accurate, but we just want to check that finding this string works + mock: setAuthHeader ? "" : "one-time password", + + authUrl: `http://localhost:${this.port}/auth`, + doneUrl: `http://localhost:${this.port}/done`, + }), + { + status: 401, + headers, + }, + ); + } + } else if (req.url.endsWith("auth")) { + expect.unreachable("url given to user, bun publish should not request"); + } else if (req.url.endsWith("done")) { + // send a fake response saying the user has authenticated successfully with the auth url + return new Response(JSON.stringify({ token: token }), { status: 200 }); + } + + expect.unreachable("unexpected url"); + }; + }; + + for (const setAuthHeader of [true, false]) { + test("mock web login" + (setAuthHeader ? "" : " (without auth header)"), async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const token = await registry.generateUser("otp" + (setAuthHeader ? "" : "noheader"), "otp"); + + using mockRegistry = Bun.serve({ + port: 0, + fetch: mockRegistryFetch({ token }), + }); + + const bunfig = ` + [install] + cache = false + registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; + await Promise.all([ + rm(join(registry.packagesPath, "otp-pkg-1"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "otp-pkg-1", + version: "2.2.2", + dependencies: { + "otp-pkg-1": "2.2.2", + }, + }), + ), + ]); + + const { out, err, exitCode } = await publish(env, packageDir); + expect(exitCode).toBe(0); + }); + } + + test("otp failure", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const token = await registry.generateUser("otp-fail", "otp"); + using mockRegistry = Bun.serve({ + port: 0, + fetch: mockRegistryFetch({ token, otpFail: true }), + }); + + const bunfig = ` + [install] + cache = false + registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; + + await Promise.all([ + rm(join(registry.packagesPath, "otp-pkg-2"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "otp-pkg-2", + version: "1.1.1", + dependencies: { + "otp-pkg-2": "1.1.1", + }, + }), + ), + ]); + + const { out, err, exitCode } = await publish(env, packageDir); + expect(exitCode).toBe(1); + expect(err).toContain(" - Received invalid OTP"); + }); + + for (const shouldIgnoreNotice of [false, true]) { + test(`npm-notice with login url${shouldIgnoreNotice ? " (ignored)" : ""}`, async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + // Situation: user has 2FA enabled account with faceid sign-in. + // They run `bun publish` with --auth-type=legacy, prompting them + // to enter their OTP. Because they have faceid sign-in, they don't + // have a code to enter, so npm sends a message in the npm-notice + // header with a url for logging in. + const token = await registry.generateUser(`otp-notice${shouldIgnoreNotice ? "-ignore" : ""}`, "otp"); + using mockRegistry = Bun.serve({ + port: 0, + fetch: mockRegistryFetch({ token, npmNotice: true, xLocalCache: shouldIgnoreNotice }), + }); + + const bunfig = ` + [install] + cache = false + registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; + + await Promise.all([ + rm(join(registry.packagesPath, "otp-pkg-3"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "otp-pkg-3", + version: "3.3.3", + dependencies: { + "otp-pkg-3": "3.3.3", + }, + }), + ), + ]); + + const { out, err, exitCode } = await publish(env, packageDir); + expect(exitCode).toBe(0); + if (shouldIgnoreNotice) { + expect(err).not.toContain(`note: visit http://localhost:${mockRegistry.port}/auth to login`); + } else { + expect(err).toContain(`note: visit http://localhost:${mockRegistry.port}/auth to login`); + } + }); + } + + const fakeCIEnvs = [ + { ci: "expo-application-services", envs: { EAS_BUILD: "hi" } }, + { ci: "codemagic", envs: { CM_BUILD_ID: "hi" } }, + { ci: "vercel", envs: { "NOW_BUILDER": "hi" } }, + ]; + for (const envInfo of fakeCIEnvs) { + test(`CI user agent name: ${envInfo.ci}`, async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const token = await registry.generateUser(`otp-${envInfo.ci}`, "otp"); + using mockRegistry = Bun.serve({ + port: 0, + fetch: mockRegistryFetch({ token, expectedCI: envInfo.ci }), + }); + + const bunfig = ` + [install] + cache = false + registry = { url = "http://localhost:${mockRegistry.port}", token = "${token}" }`; + + await Promise.all([ + rm(join(registry.packagesPath, "otp-pkg-4"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "otp-pkg-4", + version: "4.4.4", + dependencies: { + "otp-pkg-4": "4.4.4", + }, + }), + ), + ]); + + const { out, err, exitCode } = await publish( + { ...env, ...envInfo.envs, ...{ BUILDKITE: undefined, GITHUB_ACTIONS: undefined } }, + packageDir, + ); + expect(exitCode).toBe(0); + }); + } +}); + +test("can publish a package then install it", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("basic"); + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-1"), { recursive: true, force: true }), + write( + packageJson, + JSON.stringify({ + name: "publish-pkg-1", + version: "1.1.1", + dependencies: { + "publish-pkg-1": "1.1.1", + }, + }), + ), + write(join(packageDir, "bunfig.toml"), bunfig), + ]); + + const { out, err, exitCode } = await publish(env, packageDir); + expect(err).not.toContain("error:"); + expect(err).not.toContain("warn:"); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + expect(await exists(join(packageDir, "node_modules", "publish-pkg-1", "package.json"))).toBeTrue(); +}); +test("can publish from a tarball", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("tarball"); + const json = { + name: "publish-pkg-2", + version: "2.2.2", + dependencies: { + "publish-pkg-2": "2.2.2", + }, + }; + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-2"), { recursive: true, force: true }), + write(packageJson, JSON.stringify(json)), + write(join(packageDir, "bunfig.toml"), bunfig), + ]); + + await pack(packageDir, env); + + let { out, err, exitCode } = await publish(env, packageDir, "./publish-pkg-2-2.2.2.tgz"); + expect(err).not.toContain("error:"); + expect(err).not.toContain("warn:"); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + expect(await exists(join(packageDir, "node_modules", "publish-pkg-2", "package.json"))).toBeTrue(); + + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-2"), { recursive: true, force: true }), + rm(join(packageDir, "bun.lockb"), { recursive: true, force: true }), + rm(join(packageDir, "node_modules"), { recursive: true, force: true }), + ]); + + // now with an absoute path + ({ out, err, exitCode } = await publish(env, packageDir, join(packageDir, "publish-pkg-2-2.2.2.tgz"))); + expect(err).not.toContain("error:"); + expect(err).not.toContain("warn:"); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir, { savesLockfile: false }); + expect(await file(join(packageDir, "node_modules", "publish-pkg-2", "package.json")).json()).toEqual(json); +}); +test("can publish scoped packages", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("scoped-pkg"); + const json = { + name: "@scoped/pkg-1", + version: "1.1.1", + dependencies: { + "@scoped/pkg-1": "1.1.1", + }, + }; + await Promise.all([ + rm(join(registry.packagesPath, "@scoped", "pkg-1"), { recursive: true, force: true }), + write(packageJson, JSON.stringify(json)), + write(join(packageDir, "bunfig.toml"), bunfig), + ]); + + const { out, err, exitCode } = await publish(env, packageDir); + expect(err).not.toContain("error:"); + expect(err).not.toContain("warn:"); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + expect(await file(join(packageDir, "node_modules", "@scoped", "pkg-1", "package.json")).json()).toEqual(json); +}); + +for (const info of [ + { user: "bin1", bin: "bin1.js" }, + { user: "bin2", bin: { bin1: "bin1.js", bin2: "bin2.js" } }, + { user: "bin3", directories: { bin: "bins" } }, +]) { + test(`can publish and install binaries with ${JSON.stringify(info)}`, async () => { + const { packageDir, packageJson } = await registry.createTestDir({ saveTextLockfile: false }); + const publishDir = tmpdirSync(); + const bunfig = await registry.authBunfig("binaries-" + info.user); + + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-" + info.user), { recursive: true, force: true }), + write( + join(publishDir, "package.json"), + JSON.stringify({ + name: "publish-pkg-" + info.user, + version: "1.1.1", + ...info, + }), + ), + write(join(publishDir, "bunfig.toml"), bunfig), + write(join(publishDir, "bin1.js"), `#!/usr/bin/env bun\nconsole.log("bin1!")`), + write(join(publishDir, "bin2.js"), `#!/usr/bin/env bun\nconsole.log("bin2!")`), + write(join(publishDir, "bins", "bin3.js"), `#!/usr/bin/env bun\nconsole.log("bin3!")`), + write(join(publishDir, "bins", "moredir", "bin4.js"), `#!/usr/bin/env bun\nconsole.log("bin4!")`), + + write( + packageJson, + JSON.stringify({ + name: "foo", + dependencies: { + ["publish-pkg-" + info.user]: "1.1.1", + }, + }), + ), + ]); + + const { out, err, exitCode } = await publish(env, publishDir); + expect(err).not.toContain("error:"); + expect(err).not.toContain("warn:"); + expect(out).toContain(`+ publish-pkg-${info.user}@1.1.1`); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + + const results = await Promise.all([ + exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin1.bunx" : "bin1")), + exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin2.bunx" : "bin2")), + exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin3.js.bunx" : "bin3.js")), + exists(join(packageDir, "node_modules", ".bin", isWindows ? "bin4.js.bunx" : "bin4.js")), + exists(join(packageDir, "node_modules", ".bin", isWindows ? "moredir" : "moredir/bin4.js")), + exists( + join( + packageDir, + "node_modules", + ".bin", + isWindows ? `publish-pkg-${info.user}.bunx` : "publish-pkg-" + info.user, + ), + ), + ]); + + switch (info.user) { + case "bin1": { + expect(results).toEqual([false, false, false, false, false, true]); + break; + } + case "bin2": { + expect(results).toEqual([true, true, false, false, false, false]); + break; + } + case "bin3": { + expect(results).toEqual([false, false, true, true, !isWindows, false]); + break; + } + } + }); +} + +test("dependencies are installed", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const publishDir = tmpdirSync(); + const bunfig = await registry.authBunfig("manydeps"); + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-deps"), { recursive: true, force: true }), + write( + join(publishDir, "package.json"), + JSON.stringify( + { + name: "publish-pkg-deps", + version: "1.1.1", + dependencies: { + "no-deps": "1.0.0", + }, + peerDependencies: { + "a-dep": "1.0.1", + }, + optionalDependencies: { + "basic-1": "1.0.0", + }, + }, + null, + 2, + ), + ), + write(join(publishDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "foo", + dependencies: { + "publish-pkg-deps": "1.1.1", + }, + }), + ), + ]); + + let { out, err, exitCode } = await publish(env, publishDir); + expect(err).not.toContain("error:"); + expect(err).not.toContain("warn:"); + expect(out).toContain("+ publish-pkg-deps@1.1.1"); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + + const results = await Promise.all([ + exists(join(packageDir, "node_modules", "no-deps", "package.json")), + exists(join(packageDir, "node_modules", "a-dep", "package.json")), + exists(join(packageDir, "node_modules", "basic-1", "package.json")), + ]); + + expect(results).toEqual([true, true, true]); +}); + +test("can publish workspace package", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("workspace"); + const pkgJson = { + name: "publish-pkg-3", + version: "3.3.3", + dependencies: { + "publish-pkg-3": "3.3.3", + }, + }; + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-3"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "root", + workspaces: ["packages/*"], + }), + ), + write(join(packageDir, "packages", "publish-pkg-3", "package.json"), JSON.stringify(pkgJson)), + ]); + + await publish(env, join(packageDir, "packages", "publish-pkg-3")); + + await write(packageJson, JSON.stringify({ name: "root", "dependencies": { "publish-pkg-3": "3.3.3" } })); + + await runBunInstall(env, packageDir); + + expect(await file(join(packageDir, "node_modules", "publish-pkg-3", "package.json")).json()).toEqual(pkgJson); +}); + +describe("--dry-run", async () => { + test("does not publish", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("dryrun"); + await Promise.all([ + rm(join(registry.packagesPath, "dry-run-1"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "dry-run-1", + version: "1.1.1", + dependencies: { + "dry-run-1": "1.1.1", + }, + }), + ), + ]); + + const { out, err, exitCode } = await publish(env, packageDir, "--dry-run"); + expect(exitCode).toBe(0); + + expect(await exists(join(registry.packagesPath, "dry-run-1"))).toBeFalse(); + }); + test("does not publish from tarball path", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("dryruntarball"); + await Promise.all([ + rm(join(registry.packagesPath, "dry-run-2"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "dry-run-2", + version: "2.2.2", + dependencies: { + "dry-run-2": "2.2.2", + }, + }), + ), + ]); + + await pack(packageDir, env); + + const { out, err, exitCode } = await publish(env, packageDir, "./dry-run-2-2.2.2.tgz", "--dry-run"); + expect(exitCode).toBe(0); + + expect(await exists(join(registry.packagesPath, "dry-run-2"))).toBeFalse(); + }); +}); + +describe("lifecycle scripts", async () => { + const script = `const fs = require("fs"); + fs.writeFileSync(process.argv[2] + ".txt", \` +prepublishOnly: \${fs.existsSync("prepublishOnly.txt")} +publish: \${fs.existsSync("publish.txt")} +postpublish: \${fs.existsSync("postpublish.txt")} +prepack: \${fs.existsSync("prepack.txt")} +prepare: \${fs.existsSync("prepare.txt")} +postpack: \${fs.existsSync("postpack.txt")}\`)`; + const json = { + name: "publish-pkg-4", + version: "4.4.4", + scripts: { + // should happen in this order + "prepublishOnly": `${bunExe()} script.js prepublishOnly`, + "prepack": `${bunExe()} script.js prepack`, + "prepare": `${bunExe()} script.js prepare`, + "postpack": `${bunExe()} script.js postpack`, + "publish": `${bunExe()} script.js publish`, + "postpublish": `${bunExe()} script.js postpublish`, + }, + dependencies: { + "publish-pkg-4": "4.4.4", + }, + }; + + for (const arg of ["", "--dry-run"]) { + test(`should run in order${arg ? " (--dry-run)" : ""}`, async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("lifecycle" + (arg ? "dry" : "")); + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-4"), { recursive: true, force: true }), + write(packageJson, JSON.stringify(json)), + write(join(packageDir, "script.js"), script), + write(join(packageDir, "bunfig.toml"), bunfig), + ]); + + const { out, err, exitCode } = await publish(env, packageDir, arg); + expect(exitCode).toBe(0); + + const results = await Promise.all([ + file(join(packageDir, "prepublishOnly.txt")).text(), + file(join(packageDir, "prepack.txt")).text(), + file(join(packageDir, "prepare.txt")).text(), + file(join(packageDir, "postpack.txt")).text(), + file(join(packageDir, "publish.txt")).text(), + file(join(packageDir, "postpublish.txt")).text(), + ]); + + expect(results).toEqual([ + "\nprepublishOnly: false\npublish: false\npostpublish: false\nprepack: false\nprepare: false\npostpack: false", + "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: false\nprepare: false\npostpack: false", + "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: true\nprepare: false\npostpack: false", + "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: true\nprepare: true\npostpack: false", + "\nprepublishOnly: true\npublish: false\npostpublish: false\nprepack: true\nprepare: true\npostpack: true", + "\nprepublishOnly: true\npublish: true\npostpublish: false\nprepack: true\nprepare: true\npostpack: true", + ]); + }); + } + + test("--ignore-scripts", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("ignorescripts"); + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-5"), { recursive: true, force: true }), + write(packageJson, JSON.stringify(json)), + write(join(packageDir, "script.js"), script), + write(join(packageDir, "bunfig.toml"), bunfig), + ]); + + const { out, err, exitCode } = await publish(env, packageDir, "--ignore-scripts"); + expect(exitCode).toBe(0); + + const results = await Promise.all([ + exists(join(packageDir, "prepublishOnly.txt")), + exists(join(packageDir, "prepack.txt")), + exists(join(packageDir, "prepare.txt")), + exists(join(packageDir, "postpack.txt")), + exists(join(packageDir, "publish.txt")), + exists(join(packageDir, "postpublish.txt")), + ]); + + expect(results).toEqual([false, false, false, false, false, false]); + }); +}); + +test("attempting to publish a private package should fail", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("privatepackage"); + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-6"), { recursive: true, force: true }), + write( + packageJson, + JSON.stringify({ + name: "publish-pkg-6", + version: "6.6.6", + private: true, + dependencies: { + "publish-pkg-6": "6.6.6", + }, + }), + ), + write(join(packageDir, "bunfig.toml"), bunfig), + ]); + + // should fail + let { out, err, exitCode } = await publish(env, packageDir); + expect(exitCode).toBe(1); + expect(err).toContain("error: attempted to publish a private package"); + expect(await exists(join(registry.packagesPath, "publish-pkg-6-6.6.6.tgz"))).toBeFalse(); + + // try tarball + await pack(packageDir, env); + ({ out, err, exitCode } = await publish(env, packageDir, "./publish-pkg-6-6.6.6.tgz")); + expect(exitCode).toBe(1); + expect(err).toContain("error: attempted to publish a private package"); + expect(await exists(join(packageDir, "publish-pkg-6-6.6.6.tgz"))).toBeTrue(); +}); + +describe("access", async () => { + test("--access", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("accessflag"); + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-7"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write( + packageJson, + JSON.stringify({ + name: "publish-pkg-7", + version: "7.7.7", + }), + ), + ]); + + // should fail + let { out, err, exitCode } = await publish(env, packageDir, "--access", "restricted"); + expect(exitCode).toBe(1); + expect(err).toContain("error: unable to restrict access to unscoped package"); + + ({ out, err, exitCode } = await publish(env, packageDir, "--access", "public")); + expect(exitCode).toBe(0); + + expect(await exists(join(registry.packagesPath, "publish-pkg-7"))).toBeTrue(); + }); + + for (const access of ["restricted", "public"]) { + test(`access ${access}`, async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("access" + access); + + const pkgJson = { + name: "@secret/publish-pkg-8", + version: "8.8.8", + dependencies: { + "@secret/publish-pkg-8": "8.8.8", + }, + publishConfig: { + access, + }, + }; + + await Promise.all([ + rm(join(registry.packagesPath, "@secret", "publish-pkg-8"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write(packageJson, JSON.stringify(pkgJson)), + ]); + + let { out, err, exitCode } = await publish(env, packageDir); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + + expect(await file(join(packageDir, "node_modules", "@secret", "publish-pkg-8", "package.json")).json()).toEqual( + pkgJson, + ); + }); + } +}); + +describe("tag", async () => { + test("can publish with a tag", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + const bunfig = await registry.authBunfig("simpletag"); + const pkgJson = { + name: "publish-pkg-9", + version: "9.9.9", + dependencies: { + "publish-pkg-9": "simpletag", + }, + }; + await Promise.all([ + rm(join(registry.packagesPath, "publish-pkg-9"), { recursive: true, force: true }), + write(join(packageDir, "bunfig.toml"), bunfig), + write(packageJson, JSON.stringify(pkgJson)), + ]); + + let { out, err, exitCode } = await publish(env, packageDir, "--tag", "simpletag"); + expect(exitCode).toBe(0); + + await runBunInstall(env, packageDir); + expect(await file(join(packageDir, "node_modules", "publish-pkg-9", "package.json")).json()).toEqual(pkgJson); + }); +}); + +it("$npm_command is accurate during publish", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + await write( + packageJson, + JSON.stringify({ + name: "publish-pkg-10", + version: "1.0.0", + scripts: { + publish: "echo $npm_command", + }, + }), + ); + await write(join(packageDir, "bunfig.toml"), await registry.authBunfig("npm_command")); + await rm(join(registry.packagesPath, "publish-pkg-10"), { recursive: true, force: true }); + let { out, err, exitCode } = await publish(env, packageDir, "--tag", "simpletag"); + expect(err).toBe(`$ echo $npm_command\n`); + expect(out.split("\n")).toEqual([ + `bun publish ${Bun.version_with_sha}`, + ``, + `packed 95B package.json`, + ``, + `Total files: 1`, + expect.stringContaining(`Shasum: `), + expect.stringContaining(`Integrity: sha512-`), + `Unpacked size: 95B`, + expect.stringContaining(`Packed size: `), + `Tag: simpletag`, + `Access: default`, + `Registry: http://localhost:${registry.port}/`, + ``, + ` + publish-pkg-10@1.0.0`, + `publish`, + ``, + ]); + expect(exitCode).toBe(0); +}); + +it("$npm_lifecycle_event is accurate during publish", async () => { + const { packageDir, packageJson } = await registry.createTestDir(); + await write( + packageJson, + `{ + "name": "publish-pkg-11", + "version": "1.0.0", + "scripts": { + "prepublish": "echo 1 $npm_lifecycle_event", + "publish": "echo 2 $npm_lifecycle_event", + "postpublish": "echo 3 $npm_lifecycle_event", + }, + } + `, + ); + await write(join(packageDir, "bunfig.toml"), await registry.authBunfig("npm_lifecycle_event")); + await rm(join(registry.packagesPath, "publish-pkg-11"), { recursive: true, force: true }); + let { out, err, exitCode } = await publish(env, packageDir, "--tag", "simpletag"); + expect(err).toBe(`$ echo 2 $npm_lifecycle_event\n$ echo 3 $npm_lifecycle_event\n`); + expect(out.split("\n")).toEqual([ + `bun publish ${Bun.version_with_sha}`, + ``, + `packed 256B package.json`, + ``, + `Total files: 1`, + expect.stringContaining(`Shasum: `), + expect.stringContaining(`Integrity: sha512-`), + `Unpacked size: 256B`, + expect.stringContaining(`Packed size: `), + `Tag: simpletag`, + `Access: default`, + `Registry: http://localhost:${registry.port}/`, + ``, + ` + publish-pkg-11@1.0.0`, + `2 publish`, + `3 postpublish`, + ``, + ]); + expect(exitCode).toBe(0); +}); diff --git a/test/cli/install/bun-run.test.ts b/test/cli/install/bun-run.test.ts index 4697357e22ec40..79379bacdc89d7 100644 --- a/test/cli/install/bun-run.test.ts +++ b/test/cli/install/bun-run.test.ts @@ -682,10 +682,18 @@ describe("'bun run' priority", async () => { }, main: "main.js", }), + "nx.json": JSON.stringify({}), "§'.js": 'console.log("§\'.js")', - "node_modules": { ".bin": { "confabulate": `#!${bunExe()}\nconsole.log("node_modules/.bin/confabulate")` } }, + "node_modules": { + ".bin": { + "confabulate": `#!${bunExe()}\nconsole.log("node_modules/.bin/confabulate")`, + "nx": `#!${bunExe()}\nconsole.log("node_modules/.bin/nx")`, + }, + }, + "no_run_json.json": JSON.stringify({}), }); chmodSync(dir + "/node_modules/.bin/confabulate", 0o755); + chmodSync(dir + "/node_modules/.bin/nx", 0o755); const commands: { command: string[]; @@ -765,6 +773,25 @@ describe("'bun run' priority", async () => { { command: ["./.secretscript"], stdout: ".secretscript.js", stderr: "" }, { command: [dir + "/.secretscript"], stdout: ".secretscript.js", stderr: "" }, + { + command: ["no_run_json"], + stdout: "", + stderr: /error: Script not found "no_run_json"|EACCES/, + exitCode: 1, + }, + { + command: ["no_run_json.json"], + stdout: "", + stderr: /error: Module not found "no_run_json\.json"|EACCES/, + exitCode: 1, + }, + { + command: ["./no_run_json"], + stdout: "", + stderr: /error: Module not found "\.(\/|\\|\\\\)no_run_json"|EACCES/, + exitCode: 1, + }, + { command: ["/absolute"], stdout: "", @@ -786,6 +813,7 @@ describe("'bun run' priority", async () => { : [ // node_modules command { command: ["confabulate"], stdout: "node_modules/.bin/confabulate", stderr: "" }, + { command: ["nx"], stdout: "node_modules/.bin/nx", stderr: "" }, // system command { command: ["echo", "abc"], stdout: "abc", stderr: "", req_run: true }, diff --git a/test/cli/install/fixtures/invalid-optional-peer.lockb b/test/cli/install/fixtures/invalid-optional-peer.lockb new file mode 100755 index 00000000000000..b80c64c8fb699e Binary files /dev/null and b/test/cli/install/fixtures/invalid-optional-peer.lockb differ diff --git a/test/cli/install/registry/packages/debug-1/debug-1-4.4.0.tgz b/test/cli/install/registry/packages/debug-1/debug-1-4.4.0.tgz new file mode 100644 index 00000000000000..9e9825d3f300af Binary files /dev/null and b/test/cli/install/registry/packages/debug-1/debug-1-4.4.0.tgz differ diff --git a/test/cli/install/registry/packages/debug-1/package.json b/test/cli/install/registry/packages/debug-1/package.json new file mode 100644 index 00000000000000..0eda0cd62a5014 --- /dev/null +++ b/test/cli/install/registry/packages/debug-1/package.json @@ -0,0 +1,41 @@ +{ + "name": "debug-1", + "versions": { + "4.4.0": { + "name": "debug-1", + "version": "4.4.0", + "dependencies": { + "ms-1": "^2.1.3" + }, + "_id": "debug-1@4.4.0", + "_nodeVersion": "23.5.0", + "_npmVersion": "10.9.2", + "dist": { + "integrity": "sha512-uf9R1p7HgIOLOuRhqTZpFwZzkkxcZgS2eldnhsH3MWVrstXCPsjCw76rQUMHrTx0DSqfWI8fCrXpHEDBSFiHug==", + "shasum": "e3c41fed21d99b9133778cd9bd5a747f4345f824", + "tarball": "http://localhost:4873/debug-1/-/debug-1-4.4.0.tgz" + }, + "contributors": [] + } + }, + "time": { + "modified": "2025-02-01T02:30:43.460Z", + "created": "2025-02-01T02:30:43.460Z", + "4.4.0": "2025-02-01T02:30:43.460Z" + }, + "users": {}, + "dist-tags": { + "latest": "4.4.0" + }, + "_uplinks": {}, + "_distfiles": {}, + "_attachments": { + "debug-1-4.4.0.tgz": { + "shasum": "e3c41fed21d99b9133778cd9bd5a747f4345f824", + "version": "4.4.0" + } + }, + "_rev": "", + "_id": "debug-1", + "readme": "ERROR: No README data found!" +} \ No newline at end of file diff --git a/test/cli/install/registry/packages/depend-on-debug-1/depend-on-debug-1-1.0.0.tgz b/test/cli/install/registry/packages/depend-on-debug-1/depend-on-debug-1-1.0.0.tgz new file mode 100644 index 00000000000000..98761bedb5ec68 Binary files /dev/null and b/test/cli/install/registry/packages/depend-on-debug-1/depend-on-debug-1-1.0.0.tgz differ diff --git a/test/cli/install/registry/packages/depend-on-debug-1/package.json b/test/cli/install/registry/packages/depend-on-debug-1/package.json new file mode 100644 index 00000000000000..5d635ec669d0e4 --- /dev/null +++ b/test/cli/install/registry/packages/depend-on-debug-1/package.json @@ -0,0 +1,41 @@ +{ + "name": "depend-on-debug-1", + "versions": { + "1.0.0": { + "name": "depend-on-debug-1", + "version": "1.0.0", + "dependencies": { + "debug-1": "4.4.0" + }, + "_id": "depend-on-debug-1@1.0.0", + "_nodeVersion": "23.5.0", + "_npmVersion": "10.9.2", + "dist": { + "integrity": "sha512-YJ2QMT2DANZs7GKXqAmPg5oOSZJfo0QyieQ/fW5mXrdYz7l0A/mTu9tr+vBjMdPOshN0bJeD13K2vQRHETbX7w==", + "shasum": "c75fc566964c13d191a6eaf5112892f229e8a9bb", + "tarball": "http://localhost:4873/depend-on-debug-1/-/depend-on-debug-1-1.0.0.tgz" + }, + "contributors": [] + } + }, + "time": { + "modified": "2025-02-01T03:15:00.358Z", + "created": "2025-02-01T03:15:00.358Z", + "1.0.0": "2025-02-01T03:15:00.358Z" + }, + "users": {}, + "dist-tags": { + "latest": "1.0.0" + }, + "_uplinks": {}, + "_distfiles": {}, + "_attachments": { + "depend-on-debug-1-1.0.0.tgz": { + "shasum": "c75fc566964c13d191a6eaf5112892f229e8a9bb", + "version": "1.0.0" + } + }, + "_rev": "", + "_id": "depend-on-debug-1", + "readme": "ERROR: No README data found!" +} \ No newline at end of file diff --git a/test/cli/install/registry/packages/ms-1/ms-1-2.1.3.tgz b/test/cli/install/registry/packages/ms-1/ms-1-2.1.3.tgz new file mode 100644 index 00000000000000..a66136a705e269 Binary files /dev/null and b/test/cli/install/registry/packages/ms-1/ms-1-2.1.3.tgz differ diff --git a/test/cli/install/registry/packages/ms-1/package.json b/test/cli/install/registry/packages/ms-1/package.json new file mode 100644 index 00000000000000..719c23349e7c6a --- /dev/null +++ b/test/cli/install/registry/packages/ms-1/package.json @@ -0,0 +1,38 @@ +{ + "name": "ms-1", + "versions": { + "2.1.3": { + "name": "ms-1", + "version": "2.1.3", + "_id": "ms-1@2.1.3", + "_nodeVersion": "23.5.0", + "_npmVersion": "10.9.2", + "dist": { + "integrity": "sha512-FIsPf9tsd67+QNd/FEx9iRLMrolyU63pjh5U1Ny2OklxhY9bzbq3szkPjebiNltG52ydKGv6c5TaVrV10T2TRA==", + "shasum": "d180fbfb72939b2f53e401dd5329cd264288fb33", + "tarball": "http://localhost:4873/ms-1/-/ms-1-2.1.3.tgz" + }, + "contributors": [] + } + }, + "time": { + "modified": "2025-02-01T02:35:38.436Z", + "created": "2025-02-01T02:35:38.436Z", + "2.1.3": "2025-02-01T02:35:38.436Z" + }, + "users": {}, + "dist-tags": { + "latest": "2.1.3" + }, + "_uplinks": {}, + "_distfiles": {}, + "_attachments": { + "ms-1-2.1.3.tgz": { + "shasum": "d180fbfb72939b2f53e401dd5329cd264288fb33", + "version": "2.1.3" + } + }, + "_rev": "", + "_id": "ms-1", + "readme": "ERROR: No README data found!" +} \ No newline at end of file diff --git a/test/cli/install/registry/packages/npm-1/npm-1-10.9.2.tgz b/test/cli/install/registry/packages/npm-1/npm-1-10.9.2.tgz new file mode 100644 index 00000000000000..a1507b666b991e Binary files /dev/null and b/test/cli/install/registry/packages/npm-1/npm-1-10.9.2.tgz differ diff --git a/test/cli/install/registry/packages/npm-1/package.json b/test/cli/install/registry/packages/npm-1/package.json new file mode 100644 index 00000000000000..5c3fd21ed1997e --- /dev/null +++ b/test/cli/install/registry/packages/npm-1/package.json @@ -0,0 +1,46 @@ +{ + "name": "npm-1", + "versions": { + "10.9.2": { + "name": "npm-1", + "version": "10.9.2", + "dependencies": { + "ms-1": "^2.1.2", + "depend-on-debug-1": "1.0.0" + }, + "bundleDependencies": [ + "ms-1", + "depend-on-debug-1" + ], + "_id": "npm-1@10.9.2", + "_nodeVersion": "23.5.0", + "_npmVersion": "10.9.2", + "dist": { + "integrity": "sha512-Zos0KA6jxy2duN7kxjgoFoAiVqqmP60ZZjq5YWXlo3vslPwbLyyOmxCrIfJDyJSX/lvkVaXH6jKXsDYfC2jqUA==", + "shasum": "8ae88046a9b83a58bc88504c341b0c4d32e80298", + "tarball": "http://localhost:4873/npm-1/-/npm-1-10.9.2.tgz" + }, + "contributors": [] + } + }, + "time": { + "modified": "2025-02-01T03:15:31.293Z", + "created": "2025-02-01T03:15:31.293Z", + "10.9.2": "2025-02-01T03:15:31.293Z" + }, + "users": {}, + "dist-tags": { + "latest": "10.9.2" + }, + "_uplinks": {}, + "_distfiles": {}, + "_attachments": { + "npm-1-10.9.2.tgz": { + "shasum": "8ae88046a9b83a58bc88504c341b0c4d32e80298", + "version": "10.9.2" + } + }, + "_rev": "", + "_id": "npm-1", + "readme": "ERROR: No README data found!" +} \ No newline at end of file diff --git a/test/harness.ts b/test/harness.ts index dcb84f3e8886cf..5619b1095caa9e 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -186,6 +186,23 @@ export async function makeTree(base: string, tree: DirectoryTree) { } } +/** + * Recursively create files within a new temporary directory. + * + * @param basename prefix of the new temporary directory + * @param files directory tree. Each key is a folder or file, and each value is the contents of the file. Use objects for directories. + * @returns an absolute path to the new temporary directory + * + * @example + * ```ts + * const dir = tempDirWithFiles("my-test", { + * "index.js": `import foo from "./src/foo";`, + * "src": { + * "foo.js": `export default "foo";`, + * }, + * }); + * ``` + */ export function tempDirWithFiles(basename: string, files: DirectoryTree): string { const base = fs.mkdtempSync(join(fs.realpathSync(os.tmpdir()), basename + "_")); makeTree(base, files); @@ -1040,7 +1057,7 @@ export function mergeWindowEnvs(envs: Record[]) { return flat; } -export function tmpdirSync(pattern: string = "bun.test.") { +export function tmpdirSync(pattern: string = "bun.test."): string { return fs.mkdtempSync(join(fs.realpathSync.native(os.tmpdir()), pattern)); } @@ -1056,6 +1073,7 @@ export async function runBunInstall( frozenLockfile?: boolean; saveTextLockfile?: boolean; packages?: string[]; + verbose?: boolean; }, ) { const production = options?.production ?? false; @@ -1072,6 +1090,9 @@ export async function runBunInstall( if (options?.saveTextLockfile) { args.push("--save-text-lockfile"); } + if (options?.verbose) { + args.push("--verbose"); + } const { stdout, stderr, exited } = Bun.spawn({ cmd: args, cwd, @@ -1452,6 +1473,7 @@ export class VerdaccioRegistry { process: ChildProcess | undefined; configPath: string; packagesPath: string; + users: Record = {}; constructor(opts?: { configPath?: string; packagesPath?: string; verbose?: boolean }) { this.port = randomPort(); @@ -1504,10 +1526,53 @@ export class VerdaccioRegistry { this.process?.kill(0); } + /** + * returns auth token + */ + async generateUser(username: string, password: string): Promise { + if (this.users[username]) { + throw new Error(`User ${username} already exists`); + } else this.users[username] = password; + + const url = `http://localhost:${this.port}/-/user/org.couchdb.user:${username}`; + const user = { + name: username, + password: password, + email: `${username}@example.com`, + }; + + const response = await fetch(url, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(user), + }); + + if (response.ok) { + const data = await response.json(); + return data.token; + } + + throw new Error("Failed to create user:", response.statusText); + } + + async authBunfig(user: string) { + const authToken = await this.generateUser(user, user); + return ` + [install] + cache = false + registry = { url = "http://localhost:${this.port}/", token = "${authToken}" } + `; + } + async createTestDir(bunfigOpts: BunfigOpts = {}) { + await rm(join(dirname(this.configPath), "htpasswd"), { force: true }); + await rm(join(this.packagesPath, "private-pkg-dont-touch"), { force: true }); const packageDir = tmpdirSync(); const packageJson = join(packageDir, "package.json"); this.writeBunfig(packageDir, bunfigOpts); + this.users = {}; return { packageDir, packageJson }; } @@ -1515,18 +1580,21 @@ export class VerdaccioRegistry { let bunfig = ` [install] cache = "${join(dir, ".bun-cache")}" - registry = "${this.registryUrl()}" `; if ("saveTextLockfile" in opts) { bunfig += `saveTextLockfile = ${opts.saveTextLockfile} `; } + if (!opts.npm) { + bunfig += `registry = "${this.registryUrl()}"`; + } await write(join(dir, "bunfig.toml"), bunfig); } } type BunfigOpts = { saveTextLockfile?: boolean; + npm?: boolean; }; export async function readdirSorted(path: string): Promise { diff --git a/test/integration/expo-app/bun.lock b/test/integration/expo-app/bun.lock index 039a03933a0cb2..284b69d8c00656 100644 --- a/test/integration/expo-app/bun.lock +++ b/test/integration/expo-app/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "expo-app", diff --git a/test/integration/next-pages/bun.lock b/test/integration/next-pages/bun.lock index 7856950140b84f..a6a65c155e1504 100644 --- a/test/integration/next-pages/bun.lock +++ b/test/integration/next-pages/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "default-create-template", diff --git a/test/integration/next-pages/test/__snapshots__/dev-server-ssr-100.test.ts.snap b/test/integration/next-pages/test/__snapshots__/dev-server-ssr-100.test.ts.snap index 8a28f361296fbf..e189eef1ba053a 100644 --- a/test/integration/next-pages/test/__snapshots__/dev-server-ssr-100.test.ts.snap +++ b/test/integration/next-pages/test/__snapshots__/dev-server-ssr-100.test.ts.snap @@ -170,7 +170,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tailwindcss", "version": "==3.3.3", }, - "package_id": 379, + "package_id": 381, }, { "behavior": { @@ -183,7 +183,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typescript", "version": "==5.2.2", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -235,7 +235,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "chalk", "version": ">=2.4.2 <3.0.0", }, - "package_id": 425, + "package_id": 428, }, { "behavior": { @@ -417,7 +417,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-json-comments", "version": ">=3.1.1 <4.0.0", }, - "package_id": 374, + "package_id": 376, }, { "behavior": { @@ -469,7 +469,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string-width", "version": ">=5.1.2 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -483,7 +483,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string-width", "version": ">=4.2.0 <5.0.0", }, - "package_id": 367, + "package_id": 368, }, { "behavior": { @@ -496,7 +496,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -510,7 +510,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 374, }, { "behavior": { @@ -523,7 +523,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "wrap-ansi", "version": ">=8.1.0 <9.0.0", }, - "package_id": 428, + "package_id": 431, }, { "behavior": { @@ -537,7 +537,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 417, }, { "behavior": { @@ -680,7 +680,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "debug", "version": "==4.3.4", }, - "package_id": 429, + "package_id": 432, }, { "behavior": { @@ -732,7 +732,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "semver", "version": "==7.6.0", }, - "package_id": 430, + "package_id": 433, }, { "behavior": { @@ -745,7 +745,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tar-fs", "version": "==3.0.5", }, - "package_id": 381, + "package_id": 383, }, { "behavior": { @@ -758,7 +758,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "unbzip2-stream", "version": "==1.4.3", }, - "package_id": 401, + "package_id": 403, }, { "behavior": { @@ -771,7 +771,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yargs", "version": "==17.7.2", }, - "package_id": 420, + "package_id": 423, }, { "behavior": { @@ -784,7 +784,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tslib", "version": ">=2.4.0 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -849,7 +849,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 434, }, { "behavior": { @@ -862,7 +862,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 435, }, { "behavior": { @@ -1044,7 +1044,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "minimatch", "version": "==9.0.3", }, - "package_id": 432, + "package_id": 436, }, { "behavior": { @@ -1057,7 +1057,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "semver", "version": ">=7.5.4 <8.0.0", }, - "package_id": 430, + "package_id": 437, }, { "behavior": { @@ -1070,7 +1070,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ts-api-utils", "version": ">=1.0.1 <2.0.0", }, - "package_id": 389, + "package_id": 391, }, { "behavior": { @@ -1174,7 +1174,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "uri-js", "version": ">=4.2.2 <5.0.0", }, - "package_id": 405, + "package_id": 407, }, { "behavior": { @@ -1824,7 +1824,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tslib", "version": ">=2.0.1 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -2097,7 +2097,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "update-browserslist-db", "version": ">=1.0.13 <2.0.0", }, - "package_id": 404, + "package_id": 406, }, { "behavior": { @@ -2136,7 +2136,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "@types/node", "version": ">=20.12.8 <20.13.0", }, - "package_id": 431, + "package_id": 438, }, { "behavior": { @@ -2253,7 +2253,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "supports-color", "version": ">=7.1.0 <8.0.0", }, - "package_id": 377, + "package_id": 379, }, { "behavior": { @@ -2305,7 +2305,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <5.2.0", }, - "package_id": 433, + "package_id": 439, }, { "behavior": { @@ -2396,7 +2396,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "urlpattern-polyfill", "version": "==10.0.0", }, - "package_id": 406, + "package_id": 408, }, { "behavior": { @@ -2409,7 +2409,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "zod", "version": "==3.23.8", }, - "package_id": 424, + "package_id": 427, }, { "behavior": { @@ -2435,7 +2435,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -2448,7 +2448,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 416, }, { "behavior": { @@ -2475,7 +2475,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typescript", "version": ">=4.9.5", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -2566,7 +2566,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which", "version": ">=2.0.1 <3.0.0", }, - "package_id": 408, + "package_id": 410, }, { "behavior": { @@ -2878,7 +2878,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tapable", "version": ">=2.2.0 <3.0.0", }, - "package_id": 380, + "package_id": 382, }, { "behavior": { @@ -3385,7 +3385,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string.prototype.trim", "version": ">=1.2.9 <2.0.0", }, - "package_id": 369, + "package_id": 370, }, { "behavior": { @@ -3398,7 +3398,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string.prototype.trimend", "version": ">=1.0.8 <2.0.0", }, - "package_id": 370, + "package_id": 371, }, { "behavior": { @@ -3411,7 +3411,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string.prototype.trimstart", "version": ">=1.0.8 <2.0.0", }, - "package_id": 371, + "package_id": 372, }, { "behavior": { @@ -3424,7 +3424,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typed-array-buffer", "version": ">=1.0.2 <2.0.0", }, - "package_id": 395, + "package_id": 397, }, { "behavior": { @@ -3437,7 +3437,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typed-array-byte-length", "version": ">=1.0.1 <2.0.0", }, - "package_id": 396, + "package_id": 398, }, { "behavior": { @@ -3450,7 +3450,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typed-array-byte-offset", "version": ">=1.0.2 <2.0.0", }, - "package_id": 397, + "package_id": 399, }, { "behavior": { @@ -3463,7 +3463,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typed-array-length", "version": ">=1.0.6 <2.0.0", }, - "package_id": 398, + "package_id": 400, }, { "behavior": { @@ -3476,7 +3476,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "unbox-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 400, + "package_id": 402, }, { "behavior": { @@ -3489,7 +3489,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-typed-array", "version": ">=1.1.15 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -4308,7 +4308,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -4321,7 +4321,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "text-table", "version": ">=0.2.0 <0.3.0", }, - "package_id": 384, + "package_id": 386, }, { "behavior": { @@ -4348,7 +4348,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typescript", "version": ">=3.3.1", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -4478,7 +4478,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 440, }, { "behavior": { @@ -4634,7 +4634,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 441, }, { "behavior": { @@ -4712,7 +4712,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 442, }, { "behavior": { @@ -4725,7 +4725,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 443, }, { "behavior": { @@ -4868,7 +4868,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tsconfig-paths", "version": ">=3.15.0 <4.0.0", }, - "package_id": 391, + "package_id": 393, }, { "behavior": { @@ -5180,7 +5180,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 444, }, { "behavior": { @@ -5310,7 +5310,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "resolve", "version": ">=2.0.0-next.5 <3.0.0", }, - "package_id": 436, + "package_id": 445, }, { "behavior": { @@ -5336,7 +5336,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string.prototype.matchall", "version": ">=4.0.11 <5.0.0", }, - "package_id": 368, + "package_id": 369, }, { "behavior": { @@ -5492,7 +5492,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yauzl", "version": ">=2.10.0 <3.0.0", }, - "package_id": 422, + "package_id": 425, }, { "behavior": { @@ -5531,7 +5531,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <6.0.0", }, - "package_id": 433, + "package_id": 446, }, { "behavior": { @@ -5609,7 +5609,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "to-regex-range", "version": ">=5.0.1 <6.0.0", }, - "package_id": 388, + "package_id": 390, }, { "behavior": { @@ -5752,7 +5752,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -6025,7 +6025,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "minimatch", "version": ">=9.0.1 <10.0.0", }, - "package_id": 437, + "package_id": 447, }, { "behavior": { @@ -6077,7 +6077,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "type-fest", "version": ">=0.20.2 <0.21.0", }, - "package_id": 394, + "package_id": 396, }, { "behavior": { @@ -6337,7 +6337,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -6662,7 +6662,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-typed-array", "version": ">=1.1.14 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -6844,7 +6844,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -6948,7 +6948,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -7052,7 +7052,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "thenify-all", "version": ">=1.0.0 <2.0.0", }, - "package_id": 386, + "package_id": 388, }, { "behavior": { @@ -7301,7 +7301,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "postcss", "version": "==8.4.31", }, - "package_id": 438, + "package_id": 448, }, { "behavior": { @@ -7314,7 +7314,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "styled-jsx", "version": "==5.1.1", }, - "package_id": 375, + "package_id": 377, }, { "behavior": { @@ -7587,7 +7587,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -7652,7 +7652,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -7665,7 +7665,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "word-wrap", "version": ">=1.2.5 <2.0.0", }, - "package_id": 413, + "package_id": 415, }, { "behavior": { @@ -7678,7 +7678,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yocto-queue", "version": ">=0.1.0 <0.2.0", }, - "package_id": 423, + "package_id": 426, }, { "behavior": { @@ -7899,7 +7899,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "lru-cache", "version": ">=10.2.0 <11.0.0", }, - "package_id": 439, + "package_id": 449, }, { "behavior": { @@ -8070,7 +8070,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "lilconfig", "version": ">=3.0.0 <4.0.0", }, - "package_id": 440, + "package_id": 450, }, { "behavior": { @@ -8083,7 +8083,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yaml", "version": ">=2.3.4 <3.0.0", }, - "package_id": 419, + "package_id": 422, }, { "behavior": { @@ -8135,7 +8135,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "util-deprecate", "version": ">=1.0.2 <2.0.0", }, - "package_id": 407, + "package_id": 409, }, { "behavior": { @@ -8421,7 +8421,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ws", "version": "==8.17.1", }, - "package_id": 416, + "package_id": 419, }, { "behavior": { @@ -8590,7 +8590,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-builtin-type", "version": ">=1.1.3 <2.0.0", }, - "package_id": 410, + "package_id": 412, }, { "behavior": { @@ -8681,7 +8681,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -8694,7 +8694,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "glob", "version": ">=7.1.3 <8.0.0", }, - "package_id": 441, + "package_id": 451, }, { "behavior": { @@ -9123,7 +9123,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "text-decoder", "version": ">=1.1.0 <2.0.0", }, - "package_id": 383, + "package_id": 385, }, { "behavior": { @@ -9136,7 +9136,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": 442, + "package_id": 452, }, { "behavior": { @@ -9162,7 +9162,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -9175,7 +9175,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": null, + "package_id": 453, }, { "behavior": { @@ -9188,7 +9188,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "is-fullwidth-code-point", "version": ">=3.0.0 <4.0.0", }, - "package_id": null, + "package_id": 228, }, { "behavior": { @@ -9201,7 +9201,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -9513,7 +9513,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ansi-regex", "version": ">=5.0.1 <6.0.0", }, - "package_id": null, + "package_id": 55, }, { "behavior": { @@ -9630,7 +9630,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ts-interface-checker", "version": ">=0.1.9 <0.2.0", }, - "package_id": 390, + "package_id": 392, }, { "behavior": { @@ -9929,7 +9929,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "sucrase", "version": ">=3.32.0 <4.0.0", }, - "package_id": 376, + "package_id": 378, }, { "behavior": { @@ -9981,7 +9981,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "tar-stream", "version": ">=3.1.5 <4.0.0", }, - "package_id": 382, + "package_id": 384, }, { "behavior": { @@ -10059,7 +10059,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "thenify", "version": ">=3.1.0 && <4.0.0", }, - "package_id": 385, + "package_id": 387, }, { "behavior": { @@ -10085,7 +10085,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "typescript", "version": ">=4.2.0", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -10137,7 +10137,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-bom", "version": ">=3.0.0 <4.0.0", }, - "package_id": 373, + "package_id": 375, }, { "behavior": { @@ -10462,7 +10462,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -10488,7 +10488,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "through", "version": ">=2.3.8 <3.0.0", }, - "package_id": 387, + "package_id": 389, }, { "behavior": { @@ -10748,7 +10748,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -10761,7 +10761,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-collection", "version": ">=1.0.1 <2.0.0", }, - "package_id": 411, + "package_id": 413, }, { "behavior": { @@ -10774,7 +10774,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "which-typed-array", "version": ">=1.1.9 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -10930,7 +10930,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -10943,7 +10943,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ansi-styles", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 56, }, { "behavior": { @@ -10956,7 +10956,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string-width", "version": ">=4.1.0 <5.0.0", }, - "package_id": null, + "package_id": 367, }, { "behavior": { @@ -10969,7 +10969,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -11075,7 +11075,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "y18n", "version": ">=5.0.5 <6.0.0", }, - "package_id": 417, + "package_id": 420, }, { "behavior": { @@ -11088,7 +11088,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yargs-parser", "version": ">=21.1.1 <22.0.0", }, - "package_id": 421, + "package_id": 424, }, { "behavior": { @@ -11127,7 +11127,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ansi-styles", "version": ">=3.2.1 <4.0.0", }, - "package_id": 443, + "package_id": 454, }, { "behavior": { @@ -11140,7 +11140,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "escape-string-regexp", "version": ">=1.0.5 <2.0.0", }, - "package_id": 444, + "package_id": 455, }, { "behavior": { @@ -11153,7 +11153,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "supports-color", "version": ">=5.3.0 <6.0.0", }, - "package_id": 445, + "package_id": 456, }, { "behavior": { @@ -11192,7 +11192,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -11205,7 +11205,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ansi-regex", "version": ">=6.0.1 <7.0.0", }, - "package_id": 446, + "package_id": 457, }, { "behavior": { @@ -11218,7 +11218,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ansi-styles", "version": ">=6.1.0 <7.0.0", }, - "package_id": 447, + "package_id": 458, }, { "behavior": { @@ -11231,7 +11231,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "string-width", "version": ">=5.0.1 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -11244,7 +11244,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -11270,7 +11270,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": 448, + "package_id": 459, }, { "behavior": { @@ -11283,7 +11283,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": 402, + "package_id": 404, }, { "behavior": { @@ -11296,7 +11296,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -11309,7 +11309,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 460, }, { "behavior": { @@ -11322,7 +11322,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 461, }, { "behavior": { @@ -11335,7 +11335,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -11374,7 +11374,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -11387,7 +11387,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -11413,7 +11413,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "esutils", "version": ">=2.0.2 <3.0.0", }, - "package_id": null, + "package_id": 162, }, { "behavior": { @@ -11452,7 +11452,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -11465,7 +11465,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "is-glob", "version": ">=4.0.1 <5.0.0", }, - "package_id": null, + "package_id": 230, }, { "behavior": { @@ -11478,7 +11478,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 462, }, { "behavior": { @@ -11608,7 +11608,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "color-convert", "version": ">=1.9.0 <2.0.0", }, - "package_id": 450, + "package_id": 463, }, { "behavior": { @@ -11621,7 +11621,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "has-flag", "version": ">=3.0.0 <4.0.0", }, - "package_id": 451, + "package_id": 464, }, { "behavior": { @@ -11634,7 +11634,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": 418, + "package_id": 421, }, { "behavior": { @@ -11660,7 +11660,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 421, }, { "behavior": { @@ -11673,7 +11673,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "balanced-match", "version": ">=1.0.0 <2.0.0", }, - "package_id": null, + "package_id": 79, }, { "behavior": { @@ -11686,7 +11686,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "color-name", "version": "==1.1.3", }, - "package_id": 452, + "package_id": 465, }, ], "format": "v2", @@ -11731,7 +11731,9 @@ exports[`ssr works for 100-ish requests 1`] = ` "@tootallnate/quickjs-emscripten": 37, "@types/json5": 38, "@types/node": [ - 431, + 434, + 435, + 438, 39, ], "@types/prop-types": 40, @@ -11750,13 +11752,13 @@ exports[`ssr works for 100-ish requests 1`] = ` "agent-base": 53, "ajv": 54, "ansi-regex": [ - 446, + 457, 55, ], "ansi-styles": [ - 447, + 458, 56, - 443, + 454, ], "any-promise": 57, "anymatch": 58, @@ -11790,7 +11792,8 @@ exports[`ssr works for 100-ish requests 1`] = ` "basic-ftp": 86, "binary-extensions": 87, "brace-expansion": [ - 449, + 460, + 462, 88, ], "braces": 89, @@ -11805,7 +11808,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "caniuse-lite": 98, "chalk": [ 99, - 425, + 428, ], "chokidar": 100, "chromium-bidi": 101, @@ -11813,11 +11816,11 @@ exports[`ssr works for 100-ish requests 1`] = ` "cliui": 103, "color-convert": [ 104, - 450, + 463, ], "color-name": [ 105, - 452, + 465, ], "commander": 106, "concat-map": 107, @@ -11832,8 +11835,10 @@ exports[`ssr works for 100-ish requests 1`] = ` "data-view-byte-offset": 116, "debug": [ 117, - 429, - 434, + 432, + 440, + 441, + 442, ], "deep-is": 118, "default-create-template": 0, @@ -11847,13 +11852,15 @@ exports[`ssr works for 100-ish requests 1`] = ` "dlv": 126, "doctrine": [ 127, - 435, + 443, + 444, ], "eastasianwidth": 128, "electron-to-chromium": 129, "emoji-regex": [ 130, - 442, + 452, + 453, ], "end-of-stream": 131, "enhanced-resolve": 132, @@ -11870,7 +11877,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "escalade": 143, "escape-string-regexp": [ 144, - 444, + 455, ], "escodegen": 145, "eslint": 146, @@ -11920,11 +11927,12 @@ exports[`ssr works for 100-ish requests 1`] = ` "get-uri": 190, "glob": [ 191, - 441, + 451, ], "glob-parent": [ 192, - 433, + 439, + 446, ], "globals": 193, "globalthis": 194, @@ -11935,7 +11943,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "has-bigints": 199, "has-flag": [ 200, - 451, + 464, ], "has-property-descriptors": 201, "has-proto": 202, @@ -12001,7 +12009,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "language-tags": 262, "levn": 263, "lilconfig": [ - 440, + 450, 264, ], "lines-and-columns": 265, @@ -12009,15 +12017,16 @@ exports[`ssr works for 100-ish requests 1`] = ` "lodash.merge": 267, "loose-envify": 268, "lru-cache": [ - 439, + 449, 269, - 448, + 459, + 461, ], "merge2": 270, "micromatch": 271, "minimatch": [ - 437, - 432, + 447, + 436, 272, ], "minimist": 273, @@ -12063,7 +12072,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "pirates": 313, "possible-typed-array-names": 314, "postcss": [ - 438, + 448, 315, ], "postcss-import": 316, @@ -12093,7 +12102,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "regexp.prototype.flags": 340, "require-directory": 341, "resolve": [ - 436, + 445, 342, ], "resolve-from": 343, @@ -12105,7 +12114,8 @@ exports[`ssr works for 100-ish requests 1`] = ` "safe-regex-test": 349, "scheduler": 350, "semver": [ - 430, + 433, + 437, 351, ], "set-function-length": 352, @@ -12124,75 +12134,78 @@ exports[`ssr works for 100-ish requests 1`] = ` "streamsearch": 365, "streamx": 366, "string-width": [ - 426, + 429, 367, + 368, ], - "string.prototype.matchall": 368, - "string.prototype.trim": 369, - "string.prototype.trimend": 370, - "string.prototype.trimstart": 371, + "string.prototype.matchall": 369, + "string.prototype.trim": 370, + "string.prototype.trimend": 371, + "string.prototype.trimstart": 372, "strip-ansi": [ - 427, - 372, + 430, + 373, + 374, ], - "strip-bom": 373, - "strip-json-comments": 374, - "styled-jsx": 375, - "sucrase": 376, + "strip-bom": 375, + "strip-json-comments": 376, + "styled-jsx": 377, + "sucrase": 378, "supports-color": [ - 377, - 445, + 379, + 456, ], - "supports-preserve-symlinks-flag": 378, - "tailwindcss": 379, - "tapable": 380, - "tar-fs": 381, - "tar-stream": 382, - "text-decoder": 383, - "text-table": 384, - "thenify": 385, - "thenify-all": 386, - "through": 387, - "to-regex-range": 388, - "ts-api-utils": 389, - "ts-interface-checker": 390, - "tsconfig-paths": 391, - "tslib": 392, - "type-check": 393, - "type-fest": 394, - "typed-array-buffer": 395, - "typed-array-byte-length": 396, - "typed-array-byte-offset": 397, - "typed-array-length": 398, - "typescript": 399, - "unbox-primitive": 400, - "unbzip2-stream": 401, - "undici-types": 402, - "universalify": 403, - "update-browserslist-db": 404, - "uri-js": 405, - "urlpattern-polyfill": 406, - "util-deprecate": 407, - "which": 408, - "which-boxed-primitive": 409, - "which-builtin-type": 410, - "which-collection": 411, - "which-typed-array": 412, - "word-wrap": 413, + "supports-preserve-symlinks-flag": 380, + "tailwindcss": 381, + "tapable": 382, + "tar-fs": 383, + "tar-stream": 384, + "text-decoder": 385, + "text-table": 386, + "thenify": 387, + "thenify-all": 388, + "through": 389, + "to-regex-range": 390, + "ts-api-utils": 391, + "ts-interface-checker": 392, + "tsconfig-paths": 393, + "tslib": 394, + "type-check": 395, + "type-fest": 396, + "typed-array-buffer": 397, + "typed-array-byte-length": 398, + "typed-array-byte-offset": 399, + "typed-array-length": 400, + "typescript": 401, + "unbox-primitive": 402, + "unbzip2-stream": 403, + "undici-types": 404, + "universalify": 405, + "update-browserslist-db": 406, + "uri-js": 407, + "urlpattern-polyfill": 408, + "util-deprecate": 409, + "which": 410, + "which-boxed-primitive": 411, + "which-builtin-type": 412, + "which-collection": 413, + "which-typed-array": 414, + "word-wrap": 415, "wrap-ansi": [ - 428, - 414, + 431, + 416, + 417, ], - "wrappy": 415, - "ws": 416, - "y18n": 417, - "yallist": 418, - "yaml": 419, - "yargs": 420, - "yargs-parser": 421, - "yauzl": 422, - "yocto-queue": 423, - "zod": 424, + "wrappy": 418, + "ws": 419, + "y18n": 420, + "yallist": 421, + "yaml": 422, + "yargs": 423, + "yargs-parser": 424, + "yauzl": 425, + "yocto-queue": 426, + "zod": 427, }, "packages": [ { @@ -19108,6 +19121,26 @@ exports[`ssr works for 100-ish requests 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 704, + 705, + 706, + ], + "id": 368, + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "man_dir": "", + "name": "string-width", + "name_hash": "15727733666069179645", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "tag": "npm", + "value": "4.2.3", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ @@ -19124,7 +19157,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 717, 718, ], - "id": 368, + "id": 369, "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "man_dir": "", "name": "string.prototype.matchall", @@ -19145,7 +19178,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 721, 722, ], - "id": 369, + "id": 370, "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "man_dir": "", "name": "string.prototype.trim", @@ -19165,7 +19198,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 724, 725, ], - "id": 370, + "id": 371, "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "man_dir": "", "name": "string.prototype.trimend", @@ -19185,7 +19218,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 727, 728, ], - "id": 371, + "id": 372, "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "man_dir": "", "name": "string.prototype.trimstart", @@ -19203,7 +19236,25 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 729, ], - "id": 372, + "id": 373, + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "man_dir": "", + "name": "strip-ansi", + "name_hash": "13340235767065158173", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "tag": "npm", + "value": "6.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 730, + ], + "id": 374, "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "man_dir": "", "name": "strip-ansi", @@ -19219,7 +19270,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 373, + "id": 375, "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "man_dir": "", "name": "strip-bom", @@ -19235,7 +19286,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 374, + "id": 376, "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "man_dir": "", "name": "strip-json-comments", @@ -19254,7 +19305,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 731, 732, ], - "id": 375, + "id": 377, "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", "man_dir": "", "name": "styled-jsx", @@ -19281,7 +19332,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 738, 739, ], - "id": 376, + "id": 378, "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "man_dir": "", "name": "sucrase", @@ -19299,7 +19350,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 740, ], - "id": 377, + "id": 379, "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "man_dir": "", "name": "supports-color", @@ -19315,7 +19366,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 378, + "id": 380, "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "man_dir": "", "name": "supports-preserve-symlinks-flag", @@ -19357,7 +19408,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 761, 762, ], - "id": 379, + "id": 381, "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", "man_dir": "", "name": "tailwindcss", @@ -19373,7 +19424,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 380, + "id": 382, "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "man_dir": "", "name": "tapable", @@ -19394,7 +19445,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 765, 766, ], - "id": 381, + "id": 383, "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", "man_dir": "", "name": "tar-fs", @@ -19414,7 +19465,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 768, 769, ], - "id": 382, + "id": 384, "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "man_dir": "", "name": "tar-stream", @@ -19432,7 +19483,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 770, ], - "id": 383, + "id": 385, "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", "man_dir": "", "name": "text-decoder", @@ -19448,7 +19499,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 384, + "id": 386, "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "man_dir": "", "name": "text-table", @@ -19466,7 +19517,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 771, ], - "id": 385, + "id": 387, "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "man_dir": "", "name": "thenify", @@ -19484,7 +19535,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 772, ], - "id": 386, + "id": 388, "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "man_dir": "", "name": "thenify-all", @@ -19500,7 +19551,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 387, + "id": 389, "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "man_dir": "", "name": "through", @@ -19518,7 +19569,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 773, ], - "id": 388, + "id": 390, "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "man_dir": "", "name": "to-regex-range", @@ -19536,7 +19587,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 774, ], - "id": 389, + "id": 391, "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "man_dir": "", "name": "ts-api-utils", @@ -19552,7 +19603,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 390, + "id": 392, "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "man_dir": "", "name": "ts-interface-checker", @@ -19573,7 +19624,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 777, 778, ], - "id": 391, + "id": 393, "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "man_dir": "", "name": "tsconfig-paths", @@ -19589,7 +19640,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 392, + "id": 394, "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "man_dir": "", "name": "tslib", @@ -19607,7 +19658,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 779, ], - "id": 393, + "id": 395, "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "man_dir": "", "name": "type-check", @@ -19623,7 +19674,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 394, + "id": 396, "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "man_dir": "", "name": "type-fest", @@ -19643,7 +19694,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 781, 782, ], - "id": 395, + "id": 397, "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "man_dir": "", "name": "typed-array-buffer", @@ -19665,7 +19716,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 786, 787, ], - "id": 396, + "id": 398, "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "man_dir": "", "name": "typed-array-byte-length", @@ -19688,7 +19739,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 792, 793, ], - "id": 397, + "id": 399, "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "man_dir": "", "name": "typed-array-byte-offset", @@ -19711,7 +19762,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 798, 799, ], - "id": 398, + "id": 400, "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "man_dir": "", "name": "typed-array-length", @@ -19730,7 +19781,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "tsserver": "bin/tsserver", }, "dependencies": [], - "id": 399, + "id": 401, "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "man_dir": "", "name": "typescript", @@ -19751,7 +19802,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 802, 803, ], - "id": 400, + "id": 402, "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "man_dir": "", "name": "unbox-primitive", @@ -19770,7 +19821,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 804, 805, ], - "id": 401, + "id": 403, "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "man_dir": "", "name": "unbzip2-stream", @@ -19786,7 +19837,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 402, + "id": 404, "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "man_dir": "", "name": "undici-types", @@ -19802,7 +19853,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 403, + "id": 405, "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "man_dir": "", "name": "universalify", @@ -19825,7 +19876,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 807, 808, ], - "id": 404, + "id": 406, "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "man_dir": "", "name": "update-browserslist-db", @@ -19843,7 +19894,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 809, ], - "id": 405, + "id": 407, "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "man_dir": "", "name": "uri-js", @@ -19859,7 +19910,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 406, + "id": 408, "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", "man_dir": "", "name": "urlpattern-polyfill", @@ -19875,7 +19926,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 407, + "id": 409, "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "man_dir": "", "name": "util-deprecate", @@ -19896,7 +19947,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 810, ], - "id": 408, + "id": 410, "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "man_dir": "", "name": "which", @@ -19918,7 +19969,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 814, 815, ], - "id": 409, + "id": 411, "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "man_dir": "", "name": "which-boxed-primitive", @@ -19947,7 +19998,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 826, 827, ], - "id": 410, + "id": 412, "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", "man_dir": "", "name": "which-builtin-type", @@ -19968,7 +20019,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 830, 831, ], - "id": 411, + "id": 413, "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "man_dir": "", "name": "which-collection", @@ -19990,7 +20041,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 835, 836, ], - "id": 412, + "id": 414, "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "man_dir": "", "name": "which-typed-array", @@ -20006,7 +20057,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 413, + "id": 415, "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "man_dir": "", "name": "word-wrap", @@ -20026,7 +20077,27 @@ exports[`ssr works for 100-ish requests 1`] = ` 838, 839, ], - "id": 414, + "id": 416, + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "man_dir": "", + "name": "wrap-ansi", + "name_hash": "6417752039399150421", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "tag": "npm", + "value": "7.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 840, + 841, + 842, + ], + "id": 417, "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "man_dir": "", "name": "wrap-ansi", @@ -20042,7 +20113,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 415, + "id": 418, "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "man_dir": "", "name": "wrappy", @@ -20061,7 +20132,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 843, 844, ], - "id": 416, + "id": 419, "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "man_dir": "", "name": "ws", @@ -20077,7 +20148,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 417, + "id": 420, "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "man_dir": "", "name": "y18n", @@ -20093,7 +20164,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 418, + "id": 421, "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "man_dir": "", "name": "yallist", @@ -20112,7 +20183,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "name": "yaml", }, "dependencies": [], - "id": 419, + "id": 422, "integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==", "man_dir": "", "name": "yaml", @@ -20136,7 +20207,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 850, 851, ], - "id": 420, + "id": 423, "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "man_dir": "", "name": "yargs", @@ -20152,7 +20223,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 421, + "id": 424, "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "man_dir": "", "name": "yargs-parser", @@ -20171,7 +20242,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 852, 853, ], - "id": 422, + "id": 425, "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "man_dir": "", "name": "yauzl", @@ -20187,7 +20258,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 423, + "id": 426, "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "man_dir": "", "name": "yocto-queue", @@ -20203,7 +20274,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 424, + "id": 427, "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "man_dir": "", "name": "zod", @@ -20223,7 +20294,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 855, 856, ], - "id": 425, + "id": 428, "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "man_dir": "", "name": "chalk", @@ -20243,7 +20314,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 858, 859, ], - "id": 426, + "id": 429, "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "man_dir": "", "name": "string-width", @@ -20261,7 +20332,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 860, ], - "id": 427, + "id": 430, "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "man_dir": "", "name": "strip-ansi", @@ -20281,7 +20352,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 862, 863, ], - "id": 428, + "id": 431, "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "man_dir": "", "name": "wrap-ansi", @@ -20299,7 +20370,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 864, ], - "id": 429, + "id": 432, "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "man_dir": "", "name": "debug", @@ -20320,7 +20391,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 865, ], - "id": 430, + "id": 433, "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "man_dir": "", "name": "semver", @@ -20338,7 +20409,25 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 866, ], - "id": 431, + "id": 434, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 867, + ], + "id": 435, "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", "man_dir": "", "name": "@types/node", @@ -20356,7 +20445,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 868, ], - "id": 432, + "id": 436, "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "man_dir": "", "name": "minimatch", @@ -20370,29 +20459,104 @@ exports[`ssr works for 100-ish requests 1`] = ` "scripts": {}, }, { - "bin": null, + "bin": { + "file": "bin/semver.js", + "name": "semver", + }, "dependencies": [ - 871, + 869, ], - "id": 433, - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "id": 437, + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "man_dir": "", - "name": "glob-parent", - "name_hash": "11965780159102682782", + "name": "semver", + "name_hash": "16367367531761322261", "origin": "npm", "resolution": { - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "tag": "npm", - "value": "5.1.2", + "value": "7.6.0", }, "scripts": {}, }, { "bin": null, "dependencies": [ - 872, + 870, ], - "id": 434, + "id": 438, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 871, + ], + "id": 439, + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "man_dir": "", + "name": "glob-parent", + "name_hash": "11965780159102682782", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "tag": "npm", + "value": "5.1.2", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 872, + ], + "id": 440, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 873, + ], + "id": 441, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 874, + ], + "id": 442, "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "man_dir": "", "name": "debug", @@ -20410,7 +20574,25 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 875, ], - "id": 435, + "id": 443, + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "man_dir": "", + "name": "doctrine", + "name_hash": "17204823894354646410", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "tag": "npm", + "value": "2.1.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 876, + ], + "id": 444, "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "man_dir": "", "name": "doctrine", @@ -20433,7 +20615,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 878, 879, ], - "id": 436, + "id": 445, "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "man_dir": "", "name": "resolve", @@ -20446,12 +20628,30 @@ exports[`ssr works for 100-ish requests 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 880, + ], + "id": 446, + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "man_dir": "", + "name": "glob-parent", + "name_hash": "11965780159102682782", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "tag": "npm", + "value": "5.1.2", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ 881, ], - "id": 437, + "id": 447, "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "man_dir": "", "name": "minimatch", @@ -20471,7 +20671,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 883, 884, ], - "id": 438, + "id": 448, "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "man_dir": "", "name": "postcss", @@ -20487,7 +20687,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 439, + "id": 449, "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "man_dir": "", "name": "lru-cache", @@ -20503,7 +20703,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 440, + "id": 450, "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "man_dir": "", "name": "lilconfig", @@ -20526,7 +20726,7 @@ exports[`ssr works for 100-ish requests 1`] = ` 889, 890, ], - "id": 441, + "id": 451, "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "man_dir": "", "name": "glob", @@ -20542,7 +20742,23 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 442, + "id": 452, + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "man_dir": "", + "name": "emoji-regex", + "name_hash": "4954026511424972012", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "tag": "npm", + "value": "8.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [], + "id": 453, "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "man_dir": "", "name": "emoji-regex", @@ -20560,7 +20776,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 891, ], - "id": 443, + "id": 454, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "man_dir": "", "name": "ansi-styles", @@ -20576,7 +20792,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 444, + "id": 455, "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "man_dir": "", "name": "escape-string-regexp", @@ -20594,7 +20810,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 892, ], - "id": 445, + "id": 456, "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "man_dir": "", "name": "supports-color", @@ -20610,7 +20826,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 446, + "id": 457, "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "man_dir": "", "name": "ansi-regex", @@ -20626,7 +20842,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 447, + "id": 458, "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "man_dir": "", "name": "ansi-styles", @@ -20644,7 +20860,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 893, ], - "id": 448, + "id": 459, "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "man_dir": "", "name": "lru-cache", @@ -20662,7 +20878,43 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 894, ], - "id": 449, + "id": 460, + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "man_dir": "", + "name": "brace-expansion", + "name_hash": "2949258092693339993", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "tag": "npm", + "value": "2.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 895, + ], + "id": 461, + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "man_dir": "", + "name": "lru-cache", + "name_hash": "15261810304153928944", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "tag": "npm", + "value": "6.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 896, + ], + "id": 462, "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "man_dir": "", "name": "brace-expansion", @@ -20680,7 +20932,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": [ 897, ], - "id": 450, + "id": 463, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "man_dir": "", "name": "color-convert", @@ -20696,7 +20948,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 451, + "id": 464, "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "man_dir": "", "name": "has-flag", @@ -20712,7 +20964,7 @@ exports[`ssr works for 100-ish requests 1`] = ` { "bin": null, "dependencies": [], - "id": 452, + "id": 465, "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "man_dir": "", "name": "color-name", @@ -22199,243 +22451,243 @@ exports[`ssr works for 100-ish requests 1`] = ` }, "string-width-cjs": { "id": 36, - "package_id": 367, + "package_id": 368, }, "string.prototype.matchall": { "id": 409, - "package_id": 368, + "package_id": 369, }, "string.prototype.trim": { "id": 259, - "package_id": 369, + "package_id": 370, }, "string.prototype.trimend": { "id": 260, - "package_id": 370, + "package_id": 371, }, "string.prototype.trimstart": { "id": 261, - "package_id": 371, + "package_id": 372, }, "strip-ansi": { "id": 330, - "package_id": 372, + "package_id": 373, }, "strip-ansi-cjs": { "id": 38, - "package_id": 372, + "package_id": 374, }, "strip-bom": { "id": 778, - "package_id": 373, + "package_id": 375, }, "strip-json-comments": { "id": 31, - "package_id": 374, + "package_id": 376, }, "styled-jsx": { "id": 561, - "package_id": 375, + "package_id": 377, }, "sucrase": { "id": 762, - "package_id": 376, + "package_id": 378, }, "supports-color": { "id": 172, - "package_id": 377, + "package_id": 379, }, "supports-preserve-symlinks-flag": { "id": 666, - "package_id": 378, + "package_id": 380, }, "tailwindcss": { "id": 12, - "package_id": 379, + "package_id": 381, }, "tapable": { "id": 220, - "package_id": 380, + "package_id": 382, }, "tar-fs": { "id": 56, - "package_id": 381, + "package_id": 383, }, "tar-stream": { "id": 766, - "package_id": 382, + "package_id": 384, }, "text-decoder": { "id": 700, - "package_id": 383, + "package_id": 385, }, "text-table": { "id": 331, - "package_id": 384, + "package_id": 386, }, "thenify": { "id": 772, - "package_id": 385, + "package_id": 387, }, "thenify-all": { "id": 541, - "package_id": 386, + "package_id": 388, }, "through": { "id": 805, - "package_id": 387, + "package_id": 389, }, "to-regex-range": { "id": 430, - "package_id": 388, + "package_id": 390, }, "ts-api-utils": { "id": 81, - "package_id": 389, + "package_id": 391, }, "ts-interface-checker": { "id": 739, - "package_id": 390, + "package_id": 392, }, "tsconfig-paths": { "id": 373, - "package_id": 391, + "package_id": 393, }, "tslib": { "id": 59, - "package_id": 392, + "package_id": 394, }, "type-check": { "id": 533, - "package_id": 393, + "package_id": 395, }, "type-fest": { "id": 466, - "package_id": 394, + "package_id": 396, }, "typed-array-buffer": { "id": 262, - "package_id": 395, + "package_id": 397, }, "typed-array-byte-length": { "id": 263, - "package_id": 396, + "package_id": 398, }, "typed-array-byte-offset": { "id": 264, - "package_id": 397, + "package_id": 399, }, "typed-array-length": { "id": 265, - "package_id": 398, + "package_id": 400, }, "typescript": { "id": 13, - "package_id": 399, + "package_id": 401, }, "unbox-primitive": { "id": 266, - "package_id": 400, + "package_id": 402, }, "unbzip2-stream": { "id": 57, - "package_id": 401, + "package_id": 403, }, "undici-types": { - "id": 866, - "package_id": 402, + "id": 870, + "package_id": 404, }, "universalify": { "id": 441, - "package_id": 403, + "package_id": 405, }, "update-browserslist-db": { "id": 160, - "package_id": 404, + "package_id": 406, }, "uri-js": { "id": 89, - "package_id": 405, + "package_id": 407, }, "urlpattern-polyfill": { "id": 183, - "package_id": 406, + "package_id": 408, }, "util-deprecate": { "id": 624, - "package_id": 407, + "package_id": 409, }, "which": { "id": 196, - "package_id": 408, + "package_id": 410, }, "which-boxed-primitive": { "id": 803, - "package_id": 409, + "package_id": 411, }, "which-builtin-type": { "id": 659, - "package_id": 410, + "package_id": 412, }, "which-collection": { "id": 826, - "package_id": 411, + "package_id": 413, }, "which-typed-array": { "id": 267, - "package_id": 412, + "package_id": 414, }, "word-wrap": { "id": 588, - "package_id": 413, + "package_id": 415, }, "wrap-ansi": { "id": 187, - "package_id": 414, + "package_id": 416, }, "wrap-ansi-cjs": { "id": 40, - "package_id": 414, + "package_id": 417, }, "wrappy": { "id": 582, - "package_id": 415, + "package_id": 418, }, "ws": { "id": 646, - "package_id": 416, + "package_id": 419, }, "y18n": { "id": 850, - "package_id": 417, + "package_id": 420, }, "yallist": { "id": 893, - "package_id": 418, + "package_id": 421, }, "yaml": { "id": 620, - "package_id": 419, + "package_id": 422, }, "yargs": { "id": 58, - "package_id": 420, + "package_id": 423, }, "yargs-parser": { "id": 851, - "package_id": 421, + "package_id": 424, }, "yauzl": { "id": 421, - "package_id": 422, + "package_id": 425, }, "yocto-queue": { "id": 589, - "package_id": 423, + "package_id": 426, }, "zod": { "id": 184, - "package_id": 424, + "package_id": 427, }, }, "depth": 0, @@ -22446,7 +22698,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "@types/node": { "id": 163, - "package_id": 431, + "package_id": 438, }, }, "depth": 1, @@ -22457,7 +22709,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "postcss": { "id": 560, - "package_id": 438, + "package_id": 448, }, }, "depth": 1, @@ -22468,7 +22720,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "@types/node": { "id": 64, - "package_id": 431, + "package_id": 434, }, }, "depth": 1, @@ -22479,7 +22731,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "debug": { "id": 343, - "package_id": 434, + "package_id": 440, }, }, "depth": 1, @@ -22490,11 +22742,11 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "debug": { "id": 361, - "package_id": 434, + "package_id": 442, }, "doctrine": { "id": 362, - "package_id": 435, + "package_id": 443, }, }, "depth": 1, @@ -22505,11 +22757,11 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "doctrine": { "id": 397, - "package_id": 435, + "package_id": 444, }, "resolve": { "id": 407, - "package_id": 436, + "package_id": 445, }, }, "depth": 1, @@ -22520,11 +22772,11 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "debug": { "id": 51, - "package_id": 429, + "package_id": 432, }, "semver": { "id": 55, - "package_id": 430, + "package_id": 433, }, }, "depth": 1, @@ -22535,7 +22787,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "glob-parent": { "id": 176, - "package_id": 433, + "package_id": 439, }, }, "depth": 1, @@ -22546,7 +22798,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "glob-parent": { "id": 424, - "package_id": 433, + "package_id": 446, }, }, "depth": 1, @@ -22557,7 +22809,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "lilconfig": { "id": 619, - "package_id": 440, + "package_id": 450, }, }, "depth": 1, @@ -22568,7 +22820,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "minimatch": { "id": 462, - "package_id": 437, + "package_id": 447, }, }, "depth": 1, @@ -22579,11 +22831,11 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "minimatch": { "id": 79, - "package_id": 432, + "package_id": 436, }, "semver": { "id": 80, - "package_id": 430, + "package_id": 437, }, }, "depth": 1, @@ -22594,7 +22846,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "debug": { "id": 355, - "package_id": 434, + "package_id": 441, }, }, "depth": 1, @@ -22605,7 +22857,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "lru-cache": { "id": 865, - "package_id": 448, + "package_id": 459, }, }, "depth": 2, @@ -22616,7 +22868,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "glob": { "id": 667, - "package_id": 441, + "package_id": 451, }, }, "depth": 1, @@ -22627,7 +22879,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "brace-expansion": { "id": 881, - "package_id": 449, + "package_id": 462, }, }, "depth": 2, @@ -22638,7 +22890,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "lru-cache": { "id": 606, - "package_id": 439, + "package_id": 449, }, }, "depth": 1, @@ -22649,7 +22901,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "brace-expansion": { "id": 868, - "package_id": 449, + "package_id": 460, }, }, "depth": 2, @@ -22659,8 +22911,8 @@ exports[`ssr works for 100-ish requests 1`] = ` { "dependencies": { "lru-cache": { - "id": 865, - "package_id": 448, + "id": 869, + "package_id": 461, }, }, "depth": 2, @@ -22671,7 +22923,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "@types/node": { "id": 65, - "package_id": 431, + "package_id": 435, }, }, "depth": 1, @@ -22682,7 +22934,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "emoji-regex": { "id": 701, - "package_id": 442, + "package_id": 452, }, }, "depth": 1, @@ -22693,15 +22945,15 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "string-width": { "id": 35, - "package_id": 426, + "package_id": 429, }, "strip-ansi": { "id": 37, - "package_id": 427, + "package_id": 430, }, "wrap-ansi": { "id": 39, - "package_id": 428, + "package_id": 431, }, }, "depth": 1, @@ -22712,7 +22964,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "chalk": { "id": 17, - "package_id": 425, + "package_id": 428, }, }, "depth": 1, @@ -22722,8 +22974,8 @@ exports[`ssr works for 100-ish requests 1`] = ` { "dependencies": { "emoji-regex": { - "id": 701, - "package_id": 442, + "id": 704, + "package_id": 453, }, }, "depth": 1, @@ -22734,7 +22986,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "ansi-regex": { "id": 860, - "package_id": 446, + "package_id": 457, }, }, "depth": 2, @@ -22745,7 +22997,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "ansi-styles": { "id": 861, - "package_id": 447, + "package_id": 458, }, }, "depth": 2, @@ -22756,15 +23008,15 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "ansi-styles": { "id": 854, - "package_id": 443, + "package_id": 454, }, "escape-string-regexp": { "id": 855, - "package_id": 444, + "package_id": 455, }, "supports-color": { "id": 856, - "package_id": 445, + "package_id": 456, }, }, "depth": 2, @@ -22775,7 +23027,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "color-convert": { "id": 891, - "package_id": 450, + "package_id": 463, }, }, "depth": 3, @@ -22786,7 +23038,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "has-flag": { "id": 892, - "package_id": 451, + "package_id": 464, }, }, "depth": 3, @@ -22797,7 +23049,7 @@ exports[`ssr works for 100-ish requests 1`] = ` "dependencies": { "color-name": { "id": 897, - "package_id": 452, + "package_id": 465, }, }, "depth": 4, diff --git a/test/integration/next-pages/test/__snapshots__/dev-server.test.ts.snap b/test/integration/next-pages/test/__snapshots__/dev-server.test.ts.snap index c5c0b46262ee2a..29c1360d6ddbf0 100644 --- a/test/integration/next-pages/test/__snapshots__/dev-server.test.ts.snap +++ b/test/integration/next-pages/test/__snapshots__/dev-server.test.ts.snap @@ -170,7 +170,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tailwindcss", "version": "==3.3.3", }, - "package_id": 379, + "package_id": 381, }, { "behavior": { @@ -183,7 +183,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typescript", "version": "==5.2.2", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -235,7 +235,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "chalk", "version": ">=2.4.2 <3.0.0", }, - "package_id": 425, + "package_id": 428, }, { "behavior": { @@ -417,7 +417,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-json-comments", "version": ">=3.1.1 <4.0.0", }, - "package_id": 374, + "package_id": 376, }, { "behavior": { @@ -469,7 +469,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string-width", "version": ">=5.1.2 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -483,7 +483,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string-width", "version": ">=4.2.0 <5.0.0", }, - "package_id": 367, + "package_id": 368, }, { "behavior": { @@ -496,7 +496,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -510,7 +510,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 374, }, { "behavior": { @@ -523,7 +523,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "wrap-ansi", "version": ">=8.1.0 <9.0.0", }, - "package_id": 428, + "package_id": 431, }, { "behavior": { @@ -537,7 +537,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 417, }, { "behavior": { @@ -680,7 +680,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "debug", "version": "==4.3.4", }, - "package_id": 429, + "package_id": 432, }, { "behavior": { @@ -732,7 +732,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "semver", "version": "==7.6.0", }, - "package_id": 430, + "package_id": 433, }, { "behavior": { @@ -745,7 +745,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tar-fs", "version": "==3.0.5", }, - "package_id": 381, + "package_id": 383, }, { "behavior": { @@ -758,7 +758,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "unbzip2-stream", "version": "==1.4.3", }, - "package_id": 401, + "package_id": 403, }, { "behavior": { @@ -771,7 +771,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yargs", "version": "==17.7.2", }, - "package_id": 420, + "package_id": 423, }, { "behavior": { @@ -784,7 +784,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tslib", "version": ">=2.4.0 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -849,7 +849,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 434, }, { "behavior": { @@ -862,7 +862,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 435, }, { "behavior": { @@ -1044,7 +1044,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "minimatch", "version": "==9.0.3", }, - "package_id": 432, + "package_id": 436, }, { "behavior": { @@ -1057,7 +1057,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "semver", "version": ">=7.5.4 <8.0.0", }, - "package_id": 430, + "package_id": 437, }, { "behavior": { @@ -1070,7 +1070,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ts-api-utils", "version": ">=1.0.1 <2.0.0", }, - "package_id": 389, + "package_id": 391, }, { "behavior": { @@ -1174,7 +1174,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "uri-js", "version": ">=4.2.2 <5.0.0", }, - "package_id": 405, + "package_id": 407, }, { "behavior": { @@ -1824,7 +1824,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tslib", "version": ">=2.0.1 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -2097,7 +2097,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "update-browserslist-db", "version": ">=1.0.13 <2.0.0", }, - "package_id": 404, + "package_id": 406, }, { "behavior": { @@ -2136,7 +2136,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "@types/node", "version": ">=20.12.8 <20.13.0", }, - "package_id": 431, + "package_id": 438, }, { "behavior": { @@ -2253,7 +2253,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "supports-color", "version": ">=7.1.0 <8.0.0", }, - "package_id": 377, + "package_id": 379, }, { "behavior": { @@ -2305,7 +2305,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <5.2.0", }, - "package_id": 433, + "package_id": 439, }, { "behavior": { @@ -2396,7 +2396,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "urlpattern-polyfill", "version": "==10.0.0", }, - "package_id": 406, + "package_id": 408, }, { "behavior": { @@ -2409,7 +2409,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "zod", "version": "==3.23.8", }, - "package_id": 424, + "package_id": 427, }, { "behavior": { @@ -2435,7 +2435,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -2448,7 +2448,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 416, }, { "behavior": { @@ -2475,7 +2475,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typescript", "version": ">=4.9.5", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -2566,7 +2566,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which", "version": ">=2.0.1 <3.0.0", }, - "package_id": 408, + "package_id": 410, }, { "behavior": { @@ -2878,7 +2878,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tapable", "version": ">=2.2.0 <3.0.0", }, - "package_id": 380, + "package_id": 382, }, { "behavior": { @@ -3385,7 +3385,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string.prototype.trim", "version": ">=1.2.9 <2.0.0", }, - "package_id": 369, + "package_id": 370, }, { "behavior": { @@ -3398,7 +3398,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string.prototype.trimend", "version": ">=1.0.8 <2.0.0", }, - "package_id": 370, + "package_id": 371, }, { "behavior": { @@ -3411,7 +3411,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string.prototype.trimstart", "version": ">=1.0.8 <2.0.0", }, - "package_id": 371, + "package_id": 372, }, { "behavior": { @@ -3424,7 +3424,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typed-array-buffer", "version": ">=1.0.2 <2.0.0", }, - "package_id": 395, + "package_id": 397, }, { "behavior": { @@ -3437,7 +3437,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typed-array-byte-length", "version": ">=1.0.1 <2.0.0", }, - "package_id": 396, + "package_id": 398, }, { "behavior": { @@ -3450,7 +3450,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typed-array-byte-offset", "version": ">=1.0.2 <2.0.0", }, - "package_id": 397, + "package_id": 399, }, { "behavior": { @@ -3463,7 +3463,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typed-array-length", "version": ">=1.0.6 <2.0.0", }, - "package_id": 398, + "package_id": 400, }, { "behavior": { @@ -3476,7 +3476,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "unbox-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 400, + "package_id": 402, }, { "behavior": { @@ -3489,7 +3489,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-typed-array", "version": ">=1.1.15 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -4308,7 +4308,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -4321,7 +4321,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "text-table", "version": ">=0.2.0 <0.3.0", }, - "package_id": 384, + "package_id": 386, }, { "behavior": { @@ -4348,7 +4348,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typescript", "version": ">=3.3.1", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -4478,7 +4478,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 440, }, { "behavior": { @@ -4634,7 +4634,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 441, }, { "behavior": { @@ -4712,7 +4712,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 442, }, { "behavior": { @@ -4725,7 +4725,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 443, }, { "behavior": { @@ -4868,7 +4868,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tsconfig-paths", "version": ">=3.15.0 <4.0.0", }, - "package_id": 391, + "package_id": 393, }, { "behavior": { @@ -5180,7 +5180,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 444, }, { "behavior": { @@ -5310,7 +5310,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "resolve", "version": ">=2.0.0-next.5 <3.0.0", }, - "package_id": 436, + "package_id": 445, }, { "behavior": { @@ -5336,7 +5336,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string.prototype.matchall", "version": ">=4.0.11 <5.0.0", }, - "package_id": 368, + "package_id": 369, }, { "behavior": { @@ -5492,7 +5492,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yauzl", "version": ">=2.10.0 <3.0.0", }, - "package_id": 422, + "package_id": 425, }, { "behavior": { @@ -5531,7 +5531,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <6.0.0", }, - "package_id": 433, + "package_id": 446, }, { "behavior": { @@ -5609,7 +5609,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "to-regex-range", "version": ">=5.0.1 <6.0.0", }, - "package_id": 388, + "package_id": 390, }, { "behavior": { @@ -5752,7 +5752,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -6025,7 +6025,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "minimatch", "version": ">=9.0.1 <10.0.0", }, - "package_id": 437, + "package_id": 447, }, { "behavior": { @@ -6077,7 +6077,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "type-fest", "version": ">=0.20.2 <0.21.0", }, - "package_id": 394, + "package_id": 396, }, { "behavior": { @@ -6337,7 +6337,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -6662,7 +6662,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-typed-array", "version": ">=1.1.14 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -6844,7 +6844,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -6948,7 +6948,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -7052,7 +7052,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "thenify-all", "version": ">=1.0.0 <2.0.0", }, - "package_id": 386, + "package_id": 388, }, { "behavior": { @@ -7301,7 +7301,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "postcss", "version": "==8.4.31", }, - "package_id": 438, + "package_id": 448, }, { "behavior": { @@ -7314,7 +7314,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "styled-jsx", "version": "==5.1.1", }, - "package_id": 375, + "package_id": 377, }, { "behavior": { @@ -7587,7 +7587,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -7652,7 +7652,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -7665,7 +7665,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "word-wrap", "version": ">=1.2.5 <2.0.0", }, - "package_id": 413, + "package_id": 415, }, { "behavior": { @@ -7678,7 +7678,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yocto-queue", "version": ">=0.1.0 <0.2.0", }, - "package_id": 423, + "package_id": 426, }, { "behavior": { @@ -7899,7 +7899,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "lru-cache", "version": ">=10.2.0 <11.0.0", }, - "package_id": 439, + "package_id": 449, }, { "behavior": { @@ -8070,7 +8070,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "lilconfig", "version": ">=3.0.0 <4.0.0", }, - "package_id": 440, + "package_id": 450, }, { "behavior": { @@ -8083,7 +8083,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yaml", "version": ">=2.3.4 <3.0.0", }, - "package_id": 419, + "package_id": 422, }, { "behavior": { @@ -8135,7 +8135,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "util-deprecate", "version": ">=1.0.2 <2.0.0", }, - "package_id": 407, + "package_id": 409, }, { "behavior": { @@ -8421,7 +8421,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ws", "version": "==8.17.1", }, - "package_id": 416, + "package_id": 419, }, { "behavior": { @@ -8590,7 +8590,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-builtin-type", "version": ">=1.1.3 <2.0.0", }, - "package_id": 410, + "package_id": 412, }, { "behavior": { @@ -8681,7 +8681,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -8694,7 +8694,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "glob", "version": ">=7.1.3 <8.0.0", }, - "package_id": 441, + "package_id": 451, }, { "behavior": { @@ -9123,7 +9123,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "text-decoder", "version": ">=1.1.0 <2.0.0", }, - "package_id": 383, + "package_id": 385, }, { "behavior": { @@ -9136,7 +9136,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": 442, + "package_id": 452, }, { "behavior": { @@ -9162,7 +9162,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -9175,7 +9175,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": null, + "package_id": 453, }, { "behavior": { @@ -9188,7 +9188,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "is-fullwidth-code-point", "version": ">=3.0.0 <4.0.0", }, - "package_id": null, + "package_id": 228, }, { "behavior": { @@ -9201,7 +9201,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -9513,7 +9513,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ansi-regex", "version": ">=5.0.1 <6.0.0", }, - "package_id": null, + "package_id": 55, }, { "behavior": { @@ -9630,7 +9630,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ts-interface-checker", "version": ">=0.1.9 <0.2.0", }, - "package_id": 390, + "package_id": 392, }, { "behavior": { @@ -9929,7 +9929,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "sucrase", "version": ">=3.32.0 <4.0.0", }, - "package_id": 376, + "package_id": 378, }, { "behavior": { @@ -9981,7 +9981,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "tar-stream", "version": ">=3.1.5 <4.0.0", }, - "package_id": 382, + "package_id": 384, }, { "behavior": { @@ -10059,7 +10059,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "thenify", "version": ">=3.1.0 && <4.0.0", }, - "package_id": 385, + "package_id": 387, }, { "behavior": { @@ -10085,7 +10085,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "typescript", "version": ">=4.2.0", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -10137,7 +10137,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-bom", "version": ">=3.0.0 <4.0.0", }, - "package_id": 373, + "package_id": 375, }, { "behavior": { @@ -10462,7 +10462,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -10488,7 +10488,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "through", "version": ">=2.3.8 <3.0.0", }, - "package_id": 387, + "package_id": 389, }, { "behavior": { @@ -10748,7 +10748,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -10761,7 +10761,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-collection", "version": ">=1.0.1 <2.0.0", }, - "package_id": 411, + "package_id": 413, }, { "behavior": { @@ -10774,7 +10774,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "which-typed-array", "version": ">=1.1.9 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -10930,7 +10930,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -10943,7 +10943,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ansi-styles", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 56, }, { "behavior": { @@ -10956,7 +10956,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string-width", "version": ">=4.1.0 <5.0.0", }, - "package_id": null, + "package_id": 367, }, { "behavior": { @@ -10969,7 +10969,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -11075,7 +11075,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "y18n", "version": ">=5.0.5 <6.0.0", }, - "package_id": 417, + "package_id": 420, }, { "behavior": { @@ -11088,7 +11088,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yargs-parser", "version": ">=21.1.1 <22.0.0", }, - "package_id": 421, + "package_id": 424, }, { "behavior": { @@ -11127,7 +11127,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ansi-styles", "version": ">=3.2.1 <4.0.0", }, - "package_id": 443, + "package_id": 454, }, { "behavior": { @@ -11140,7 +11140,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "escape-string-regexp", "version": ">=1.0.5 <2.0.0", }, - "package_id": 444, + "package_id": 455, }, { "behavior": { @@ -11153,7 +11153,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "supports-color", "version": ">=5.3.0 <6.0.0", }, - "package_id": 445, + "package_id": 456, }, { "behavior": { @@ -11192,7 +11192,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -11205,7 +11205,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ansi-regex", "version": ">=6.0.1 <7.0.0", }, - "package_id": 446, + "package_id": 457, }, { "behavior": { @@ -11218,7 +11218,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ansi-styles", "version": ">=6.1.0 <7.0.0", }, - "package_id": 447, + "package_id": 458, }, { "behavior": { @@ -11231,7 +11231,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "string-width", "version": ">=5.0.1 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -11244,7 +11244,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -11270,7 +11270,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": 448, + "package_id": 459, }, { "behavior": { @@ -11283,7 +11283,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": 402, + "package_id": 404, }, { "behavior": { @@ -11296,7 +11296,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -11309,7 +11309,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 460, }, { "behavior": { @@ -11322,7 +11322,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 461, }, { "behavior": { @@ -11335,7 +11335,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -11374,7 +11374,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -11387,7 +11387,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -11413,7 +11413,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "esutils", "version": ">=2.0.2 <3.0.0", }, - "package_id": null, + "package_id": 162, }, { "behavior": { @@ -11452,7 +11452,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -11465,7 +11465,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "is-glob", "version": ">=4.0.1 <5.0.0", }, - "package_id": null, + "package_id": 230, }, { "behavior": { @@ -11478,7 +11478,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 462, }, { "behavior": { @@ -11608,7 +11608,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "color-convert", "version": ">=1.9.0 <2.0.0", }, - "package_id": 450, + "package_id": 463, }, { "behavior": { @@ -11621,7 +11621,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "has-flag", "version": ">=3.0.0 <4.0.0", }, - "package_id": 451, + "package_id": 464, }, { "behavior": { @@ -11634,7 +11634,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": 418, + "package_id": 421, }, { "behavior": { @@ -11660,7 +11660,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 421, }, { "behavior": { @@ -11673,7 +11673,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "balanced-match", "version": ">=1.0.0 <2.0.0", }, - "package_id": null, + "package_id": 79, }, { "behavior": { @@ -11686,7 +11686,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "color-name", "version": "==1.1.3", }, - "package_id": 452, + "package_id": 465, }, ], "format": "v2", @@ -11731,7 +11731,9 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "@tootallnate/quickjs-emscripten": 37, "@types/json5": 38, "@types/node": [ - 431, + 434, + 435, + 438, 39, ], "@types/prop-types": 40, @@ -11750,13 +11752,13 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "agent-base": 53, "ajv": 54, "ansi-regex": [ - 446, + 457, 55, ], "ansi-styles": [ - 447, + 458, 56, - 443, + 454, ], "any-promise": 57, "anymatch": 58, @@ -11790,7 +11792,8 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "basic-ftp": 86, "binary-extensions": 87, "brace-expansion": [ - 449, + 460, + 462, 88, ], "braces": 89, @@ -11805,7 +11808,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "caniuse-lite": 98, "chalk": [ 99, - 425, + 428, ], "chokidar": 100, "chromium-bidi": 101, @@ -11813,11 +11816,11 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "cliui": 103, "color-convert": [ 104, - 450, + 463, ], "color-name": [ 105, - 452, + 465, ], "commander": 106, "concat-map": 107, @@ -11832,8 +11835,10 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "data-view-byte-offset": 116, "debug": [ 117, - 429, - 434, + 432, + 440, + 441, + 442, ], "deep-is": 118, "default-create-template": 0, @@ -11847,13 +11852,15 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dlv": 126, "doctrine": [ 127, - 435, + 443, + 444, ], "eastasianwidth": 128, "electron-to-chromium": 129, "emoji-regex": [ 130, - 442, + 452, + 453, ], "end-of-stream": 131, "enhanced-resolve": 132, @@ -11870,7 +11877,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "escalade": 143, "escape-string-regexp": [ 144, - 444, + 455, ], "escodegen": 145, "eslint": 146, @@ -11920,11 +11927,12 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "get-uri": 190, "glob": [ 191, - 441, + 451, ], "glob-parent": [ 192, - 433, + 439, + 446, ], "globals": 193, "globalthis": 194, @@ -11935,7 +11943,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "has-bigints": 199, "has-flag": [ 200, - 451, + 464, ], "has-property-descriptors": 201, "has-proto": 202, @@ -12001,7 +12009,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "language-tags": 262, "levn": 263, "lilconfig": [ - 440, + 450, 264, ], "lines-and-columns": 265, @@ -12009,15 +12017,16 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "lodash.merge": 267, "loose-envify": 268, "lru-cache": [ - 439, + 449, 269, - 448, + 459, + 461, ], "merge2": 270, "micromatch": 271, "minimatch": [ - 437, - 432, + 447, + 436, 272, ], "minimist": 273, @@ -12063,7 +12072,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "pirates": 313, "possible-typed-array-names": 314, "postcss": [ - 438, + 448, 315, ], "postcss-import": 316, @@ -12093,7 +12102,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "regexp.prototype.flags": 340, "require-directory": 341, "resolve": [ - 436, + 445, 342, ], "resolve-from": 343, @@ -12105,7 +12114,8 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "safe-regex-test": 349, "scheduler": 350, "semver": [ - 430, + 433, + 437, 351, ], "set-function-length": 352, @@ -12124,75 +12134,78 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "streamsearch": 365, "streamx": 366, "string-width": [ - 426, + 429, 367, + 368, ], - "string.prototype.matchall": 368, - "string.prototype.trim": 369, - "string.prototype.trimend": 370, - "string.prototype.trimstart": 371, + "string.prototype.matchall": 369, + "string.prototype.trim": 370, + "string.prototype.trimend": 371, + "string.prototype.trimstart": 372, "strip-ansi": [ - 427, - 372, + 430, + 373, + 374, ], - "strip-bom": 373, - "strip-json-comments": 374, - "styled-jsx": 375, - "sucrase": 376, + "strip-bom": 375, + "strip-json-comments": 376, + "styled-jsx": 377, + "sucrase": 378, "supports-color": [ - 377, - 445, + 379, + 456, ], - "supports-preserve-symlinks-flag": 378, - "tailwindcss": 379, - "tapable": 380, - "tar-fs": 381, - "tar-stream": 382, - "text-decoder": 383, - "text-table": 384, - "thenify": 385, - "thenify-all": 386, - "through": 387, - "to-regex-range": 388, - "ts-api-utils": 389, - "ts-interface-checker": 390, - "tsconfig-paths": 391, - "tslib": 392, - "type-check": 393, - "type-fest": 394, - "typed-array-buffer": 395, - "typed-array-byte-length": 396, - "typed-array-byte-offset": 397, - "typed-array-length": 398, - "typescript": 399, - "unbox-primitive": 400, - "unbzip2-stream": 401, - "undici-types": 402, - "universalify": 403, - "update-browserslist-db": 404, - "uri-js": 405, - "urlpattern-polyfill": 406, - "util-deprecate": 407, - "which": 408, - "which-boxed-primitive": 409, - "which-builtin-type": 410, - "which-collection": 411, - "which-typed-array": 412, - "word-wrap": 413, + "supports-preserve-symlinks-flag": 380, + "tailwindcss": 381, + "tapable": 382, + "tar-fs": 383, + "tar-stream": 384, + "text-decoder": 385, + "text-table": 386, + "thenify": 387, + "thenify-all": 388, + "through": 389, + "to-regex-range": 390, + "ts-api-utils": 391, + "ts-interface-checker": 392, + "tsconfig-paths": 393, + "tslib": 394, + "type-check": 395, + "type-fest": 396, + "typed-array-buffer": 397, + "typed-array-byte-length": 398, + "typed-array-byte-offset": 399, + "typed-array-length": 400, + "typescript": 401, + "unbox-primitive": 402, + "unbzip2-stream": 403, + "undici-types": 404, + "universalify": 405, + "update-browserslist-db": 406, + "uri-js": 407, + "urlpattern-polyfill": 408, + "util-deprecate": 409, + "which": 410, + "which-boxed-primitive": 411, + "which-builtin-type": 412, + "which-collection": 413, + "which-typed-array": 414, + "word-wrap": 415, "wrap-ansi": [ - 428, - 414, + 431, + 416, + 417, ], - "wrappy": 415, - "ws": 416, - "y18n": 417, - "yallist": 418, - "yaml": 419, - "yargs": 420, - "yargs-parser": 421, - "yauzl": 422, - "yocto-queue": 423, - "zod": 424, + "wrappy": 418, + "ws": 419, + "y18n": 420, + "yallist": 421, + "yaml": 422, + "yargs": 423, + "yargs-parser": 424, + "yauzl": 425, + "yocto-queue": 426, + "zod": 427, }, "packages": [ { @@ -19108,6 +19121,26 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 704, + 705, + 706, + ], + "id": 368, + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "man_dir": "", + "name": "string-width", + "name_hash": "15727733666069179645", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "tag": "npm", + "value": "4.2.3", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ @@ -19124,7 +19157,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 717, 718, ], - "id": 368, + "id": 369, "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "man_dir": "", "name": "string.prototype.matchall", @@ -19145,7 +19178,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 721, 722, ], - "id": 369, + "id": 370, "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "man_dir": "", "name": "string.prototype.trim", @@ -19165,7 +19198,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 724, 725, ], - "id": 370, + "id": 371, "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "man_dir": "", "name": "string.prototype.trimend", @@ -19185,7 +19218,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 727, 728, ], - "id": 371, + "id": 372, "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "man_dir": "", "name": "string.prototype.trimstart", @@ -19203,7 +19236,25 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 729, ], - "id": 372, + "id": 373, + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "man_dir": "", + "name": "strip-ansi", + "name_hash": "13340235767065158173", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "tag": "npm", + "value": "6.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 730, + ], + "id": 374, "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "man_dir": "", "name": "strip-ansi", @@ -19219,7 +19270,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 373, + "id": 375, "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "man_dir": "", "name": "strip-bom", @@ -19235,7 +19286,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 374, + "id": 376, "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "man_dir": "", "name": "strip-json-comments", @@ -19254,7 +19305,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 731, 732, ], - "id": 375, + "id": 377, "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", "man_dir": "", "name": "styled-jsx", @@ -19281,7 +19332,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 738, 739, ], - "id": 376, + "id": 378, "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "man_dir": "", "name": "sucrase", @@ -19299,7 +19350,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 740, ], - "id": 377, + "id": 379, "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "man_dir": "", "name": "supports-color", @@ -19315,7 +19366,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 378, + "id": 380, "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "man_dir": "", "name": "supports-preserve-symlinks-flag", @@ -19357,7 +19408,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 761, 762, ], - "id": 379, + "id": 381, "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", "man_dir": "", "name": "tailwindcss", @@ -19373,7 +19424,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 380, + "id": 382, "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "man_dir": "", "name": "tapable", @@ -19394,7 +19445,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 765, 766, ], - "id": 381, + "id": 383, "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", "man_dir": "", "name": "tar-fs", @@ -19414,7 +19465,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 768, 769, ], - "id": 382, + "id": 384, "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "man_dir": "", "name": "tar-stream", @@ -19432,7 +19483,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 770, ], - "id": 383, + "id": 385, "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", "man_dir": "", "name": "text-decoder", @@ -19448,7 +19499,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 384, + "id": 386, "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "man_dir": "", "name": "text-table", @@ -19466,7 +19517,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 771, ], - "id": 385, + "id": 387, "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "man_dir": "", "name": "thenify", @@ -19484,7 +19535,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 772, ], - "id": 386, + "id": 388, "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "man_dir": "", "name": "thenify-all", @@ -19500,7 +19551,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 387, + "id": 389, "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "man_dir": "", "name": "through", @@ -19518,7 +19569,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 773, ], - "id": 388, + "id": 390, "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "man_dir": "", "name": "to-regex-range", @@ -19536,7 +19587,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 774, ], - "id": 389, + "id": 391, "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "man_dir": "", "name": "ts-api-utils", @@ -19552,7 +19603,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 390, + "id": 392, "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "man_dir": "", "name": "ts-interface-checker", @@ -19573,7 +19624,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 777, 778, ], - "id": 391, + "id": 393, "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "man_dir": "", "name": "tsconfig-paths", @@ -19589,7 +19640,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 392, + "id": 394, "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "man_dir": "", "name": "tslib", @@ -19607,7 +19658,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 779, ], - "id": 393, + "id": 395, "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "man_dir": "", "name": "type-check", @@ -19623,7 +19674,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 394, + "id": 396, "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "man_dir": "", "name": "type-fest", @@ -19643,7 +19694,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 781, 782, ], - "id": 395, + "id": 397, "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "man_dir": "", "name": "typed-array-buffer", @@ -19665,7 +19716,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 786, 787, ], - "id": 396, + "id": 398, "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "man_dir": "", "name": "typed-array-byte-length", @@ -19688,7 +19739,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 792, 793, ], - "id": 397, + "id": 399, "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "man_dir": "", "name": "typed-array-byte-offset", @@ -19711,7 +19762,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 798, 799, ], - "id": 398, + "id": 400, "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "man_dir": "", "name": "typed-array-length", @@ -19730,7 +19781,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "tsserver": "bin/tsserver", }, "dependencies": [], - "id": 399, + "id": 401, "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "man_dir": "", "name": "typescript", @@ -19751,7 +19802,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 802, 803, ], - "id": 400, + "id": 402, "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "man_dir": "", "name": "unbox-primitive", @@ -19770,7 +19821,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 804, 805, ], - "id": 401, + "id": 403, "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "man_dir": "", "name": "unbzip2-stream", @@ -19786,7 +19837,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 402, + "id": 404, "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "man_dir": "", "name": "undici-types", @@ -19802,7 +19853,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 403, + "id": 405, "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "man_dir": "", "name": "universalify", @@ -19825,7 +19876,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 807, 808, ], - "id": 404, + "id": 406, "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "man_dir": "", "name": "update-browserslist-db", @@ -19843,7 +19894,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 809, ], - "id": 405, + "id": 407, "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "man_dir": "", "name": "uri-js", @@ -19859,7 +19910,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 406, + "id": 408, "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", "man_dir": "", "name": "urlpattern-polyfill", @@ -19875,7 +19926,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 407, + "id": 409, "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "man_dir": "", "name": "util-deprecate", @@ -19896,7 +19947,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 810, ], - "id": 408, + "id": 410, "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "man_dir": "", "name": "which", @@ -19918,7 +19969,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 814, 815, ], - "id": 409, + "id": 411, "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "man_dir": "", "name": "which-boxed-primitive", @@ -19947,7 +19998,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 826, 827, ], - "id": 410, + "id": 412, "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", "man_dir": "", "name": "which-builtin-type", @@ -19968,7 +20019,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 830, 831, ], - "id": 411, + "id": 413, "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "man_dir": "", "name": "which-collection", @@ -19990,7 +20041,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 835, 836, ], - "id": 412, + "id": 414, "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "man_dir": "", "name": "which-typed-array", @@ -20006,7 +20057,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 413, + "id": 415, "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "man_dir": "", "name": "word-wrap", @@ -20026,7 +20077,27 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 838, 839, ], - "id": 414, + "id": 416, + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "man_dir": "", + "name": "wrap-ansi", + "name_hash": "6417752039399150421", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "tag": "npm", + "value": "7.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 840, + 841, + 842, + ], + "id": 417, "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "man_dir": "", "name": "wrap-ansi", @@ -20042,7 +20113,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 415, + "id": 418, "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "man_dir": "", "name": "wrappy", @@ -20061,7 +20132,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 843, 844, ], - "id": 416, + "id": 419, "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "man_dir": "", "name": "ws", @@ -20077,7 +20148,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 417, + "id": 420, "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "man_dir": "", "name": "y18n", @@ -20093,7 +20164,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 418, + "id": 421, "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "man_dir": "", "name": "yallist", @@ -20112,7 +20183,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "name": "yaml", }, "dependencies": [], - "id": 419, + "id": 422, "integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==", "man_dir": "", "name": "yaml", @@ -20136,7 +20207,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 850, 851, ], - "id": 420, + "id": 423, "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "man_dir": "", "name": "yargs", @@ -20152,7 +20223,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 421, + "id": 424, "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "man_dir": "", "name": "yargs-parser", @@ -20171,7 +20242,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 852, 853, ], - "id": 422, + "id": 425, "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "man_dir": "", "name": "yauzl", @@ -20187,7 +20258,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 423, + "id": 426, "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "man_dir": "", "name": "yocto-queue", @@ -20203,7 +20274,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 424, + "id": 427, "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "man_dir": "", "name": "zod", @@ -20223,7 +20294,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 855, 856, ], - "id": 425, + "id": 428, "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "man_dir": "", "name": "chalk", @@ -20243,7 +20314,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 858, 859, ], - "id": 426, + "id": 429, "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "man_dir": "", "name": "string-width", @@ -20261,7 +20332,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 860, ], - "id": 427, + "id": 430, "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "man_dir": "", "name": "strip-ansi", @@ -20281,7 +20352,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 862, 863, ], - "id": 428, + "id": 431, "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "man_dir": "", "name": "wrap-ansi", @@ -20299,7 +20370,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 864, ], - "id": 429, + "id": 432, "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "man_dir": "", "name": "debug", @@ -20320,7 +20391,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 865, ], - "id": 430, + "id": 433, "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "man_dir": "", "name": "semver", @@ -20338,7 +20409,25 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 866, ], - "id": 431, + "id": 434, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 867, + ], + "id": 435, "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", "man_dir": "", "name": "@types/node", @@ -20356,7 +20445,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 868, ], - "id": 432, + "id": 436, "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "man_dir": "", "name": "minimatch", @@ -20370,29 +20459,104 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "scripts": {}, }, { - "bin": null, + "bin": { + "file": "bin/semver.js", + "name": "semver", + }, "dependencies": [ - 871, + 869, ], - "id": 433, - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "id": 437, + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "man_dir": "", - "name": "glob-parent", - "name_hash": "11965780159102682782", + "name": "semver", + "name_hash": "16367367531761322261", "origin": "npm", "resolution": { - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "tag": "npm", - "value": "5.1.2", + "value": "7.6.0", }, "scripts": {}, }, { "bin": null, "dependencies": [ - 872, + 870, ], - "id": 434, + "id": 438, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 871, + ], + "id": 439, + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "man_dir": "", + "name": "glob-parent", + "name_hash": "11965780159102682782", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "tag": "npm", + "value": "5.1.2", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 872, + ], + "id": 440, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 873, + ], + "id": 441, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 874, + ], + "id": 442, "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "man_dir": "", "name": "debug", @@ -20410,7 +20574,25 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 875, ], - "id": 435, + "id": 443, + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "man_dir": "", + "name": "doctrine", + "name_hash": "17204823894354646410", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "tag": "npm", + "value": "2.1.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 876, + ], + "id": 444, "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "man_dir": "", "name": "doctrine", @@ -20433,7 +20615,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 878, 879, ], - "id": 436, + "id": 445, "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "man_dir": "", "name": "resolve", @@ -20446,12 +20628,30 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 880, + ], + "id": 446, + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "man_dir": "", + "name": "glob-parent", + "name_hash": "11965780159102682782", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "tag": "npm", + "value": "5.1.2", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ 881, ], - "id": 437, + "id": 447, "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "man_dir": "", "name": "minimatch", @@ -20471,7 +20671,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 883, 884, ], - "id": 438, + "id": 448, "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "man_dir": "", "name": "postcss", @@ -20487,7 +20687,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 439, + "id": 449, "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "man_dir": "", "name": "lru-cache", @@ -20503,7 +20703,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 440, + "id": 450, "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "man_dir": "", "name": "lilconfig", @@ -20526,7 +20726,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` 889, 890, ], - "id": 441, + "id": 451, "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "man_dir": "", "name": "glob", @@ -20542,7 +20742,23 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 442, + "id": 452, + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "man_dir": "", + "name": "emoji-regex", + "name_hash": "4954026511424972012", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "tag": "npm", + "value": "8.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [], + "id": 453, "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "man_dir": "", "name": "emoji-regex", @@ -20560,7 +20776,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 891, ], - "id": 443, + "id": 454, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "man_dir": "", "name": "ansi-styles", @@ -20576,7 +20792,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 444, + "id": 455, "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "man_dir": "", "name": "escape-string-regexp", @@ -20594,7 +20810,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 892, ], - "id": 445, + "id": 456, "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "man_dir": "", "name": "supports-color", @@ -20610,7 +20826,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 446, + "id": 457, "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "man_dir": "", "name": "ansi-regex", @@ -20626,7 +20842,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 447, + "id": 458, "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "man_dir": "", "name": "ansi-styles", @@ -20644,7 +20860,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 893, ], - "id": 448, + "id": 459, "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "man_dir": "", "name": "lru-cache", @@ -20662,7 +20878,43 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 894, ], - "id": 449, + "id": 460, + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "man_dir": "", + "name": "brace-expansion", + "name_hash": "2949258092693339993", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "tag": "npm", + "value": "2.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 895, + ], + "id": 461, + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "man_dir": "", + "name": "lru-cache", + "name_hash": "15261810304153928944", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "tag": "npm", + "value": "6.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 896, + ], + "id": 462, "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "man_dir": "", "name": "brace-expansion", @@ -20680,7 +20932,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": [ 897, ], - "id": 450, + "id": 463, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "man_dir": "", "name": "color-convert", @@ -20696,7 +20948,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 451, + "id": 464, "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "man_dir": "", "name": "has-flag", @@ -20712,7 +20964,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "bin": null, "dependencies": [], - "id": 452, + "id": 465, "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "man_dir": "", "name": "color-name", @@ -22199,243 +22451,243 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` }, "string-width-cjs": { "id": 36, - "package_id": 367, + "package_id": 368, }, "string.prototype.matchall": { "id": 409, - "package_id": 368, + "package_id": 369, }, "string.prototype.trim": { "id": 259, - "package_id": 369, + "package_id": 370, }, "string.prototype.trimend": { "id": 260, - "package_id": 370, + "package_id": 371, }, "string.prototype.trimstart": { "id": 261, - "package_id": 371, + "package_id": 372, }, "strip-ansi": { "id": 330, - "package_id": 372, + "package_id": 373, }, "strip-ansi-cjs": { "id": 38, - "package_id": 372, + "package_id": 374, }, "strip-bom": { "id": 778, - "package_id": 373, + "package_id": 375, }, "strip-json-comments": { "id": 31, - "package_id": 374, + "package_id": 376, }, "styled-jsx": { "id": 561, - "package_id": 375, + "package_id": 377, }, "sucrase": { "id": 762, - "package_id": 376, + "package_id": 378, }, "supports-color": { "id": 172, - "package_id": 377, + "package_id": 379, }, "supports-preserve-symlinks-flag": { "id": 666, - "package_id": 378, + "package_id": 380, }, "tailwindcss": { "id": 12, - "package_id": 379, + "package_id": 381, }, "tapable": { "id": 220, - "package_id": 380, + "package_id": 382, }, "tar-fs": { "id": 56, - "package_id": 381, + "package_id": 383, }, "tar-stream": { "id": 766, - "package_id": 382, + "package_id": 384, }, "text-decoder": { "id": 700, - "package_id": 383, + "package_id": 385, }, "text-table": { "id": 331, - "package_id": 384, + "package_id": 386, }, "thenify": { "id": 772, - "package_id": 385, + "package_id": 387, }, "thenify-all": { "id": 541, - "package_id": 386, + "package_id": 388, }, "through": { "id": 805, - "package_id": 387, + "package_id": 389, }, "to-regex-range": { "id": 430, - "package_id": 388, + "package_id": 390, }, "ts-api-utils": { "id": 81, - "package_id": 389, + "package_id": 391, }, "ts-interface-checker": { "id": 739, - "package_id": 390, + "package_id": 392, }, "tsconfig-paths": { "id": 373, - "package_id": 391, + "package_id": 393, }, "tslib": { "id": 59, - "package_id": 392, + "package_id": 394, }, "type-check": { "id": 533, - "package_id": 393, + "package_id": 395, }, "type-fest": { "id": 466, - "package_id": 394, + "package_id": 396, }, "typed-array-buffer": { "id": 262, - "package_id": 395, + "package_id": 397, }, "typed-array-byte-length": { "id": 263, - "package_id": 396, + "package_id": 398, }, "typed-array-byte-offset": { "id": 264, - "package_id": 397, + "package_id": 399, }, "typed-array-length": { "id": 265, - "package_id": 398, + "package_id": 400, }, "typescript": { "id": 13, - "package_id": 399, + "package_id": 401, }, "unbox-primitive": { "id": 266, - "package_id": 400, + "package_id": 402, }, "unbzip2-stream": { "id": 57, - "package_id": 401, + "package_id": 403, }, "undici-types": { - "id": 866, - "package_id": 402, + "id": 870, + "package_id": 404, }, "universalify": { "id": 441, - "package_id": 403, + "package_id": 405, }, "update-browserslist-db": { "id": 160, - "package_id": 404, + "package_id": 406, }, "uri-js": { "id": 89, - "package_id": 405, + "package_id": 407, }, "urlpattern-polyfill": { "id": 183, - "package_id": 406, + "package_id": 408, }, "util-deprecate": { "id": 624, - "package_id": 407, + "package_id": 409, }, "which": { "id": 196, - "package_id": 408, + "package_id": 410, }, "which-boxed-primitive": { "id": 803, - "package_id": 409, + "package_id": 411, }, "which-builtin-type": { "id": 659, - "package_id": 410, + "package_id": 412, }, "which-collection": { "id": 826, - "package_id": 411, + "package_id": 413, }, "which-typed-array": { "id": 267, - "package_id": 412, + "package_id": 414, }, "word-wrap": { "id": 588, - "package_id": 413, + "package_id": 415, }, "wrap-ansi": { "id": 187, - "package_id": 414, + "package_id": 416, }, "wrap-ansi-cjs": { "id": 40, - "package_id": 414, + "package_id": 417, }, "wrappy": { "id": 582, - "package_id": 415, + "package_id": 418, }, "ws": { "id": 646, - "package_id": 416, + "package_id": 419, }, "y18n": { "id": 850, - "package_id": 417, + "package_id": 420, }, "yallist": { "id": 893, - "package_id": 418, + "package_id": 421, }, "yaml": { "id": 620, - "package_id": 419, + "package_id": 422, }, "yargs": { "id": 58, - "package_id": 420, + "package_id": 423, }, "yargs-parser": { "id": 851, - "package_id": 421, + "package_id": 424, }, "yauzl": { "id": 421, - "package_id": 422, + "package_id": 425, }, "yocto-queue": { "id": 589, - "package_id": 423, + "package_id": 426, }, "zod": { "id": 184, - "package_id": 424, + "package_id": 427, }, }, "depth": 0, @@ -22446,7 +22698,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "@types/node": { "id": 163, - "package_id": 431, + "package_id": 438, }, }, "depth": 1, @@ -22457,7 +22709,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "postcss": { "id": 560, - "package_id": 438, + "package_id": 448, }, }, "depth": 1, @@ -22468,7 +22720,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "@types/node": { "id": 64, - "package_id": 431, + "package_id": 434, }, }, "depth": 1, @@ -22479,7 +22731,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "debug": { "id": 343, - "package_id": 434, + "package_id": 440, }, }, "depth": 1, @@ -22490,11 +22742,11 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "debug": { "id": 361, - "package_id": 434, + "package_id": 442, }, "doctrine": { "id": 362, - "package_id": 435, + "package_id": 443, }, }, "depth": 1, @@ -22505,11 +22757,11 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "doctrine": { "id": 397, - "package_id": 435, + "package_id": 444, }, "resolve": { "id": 407, - "package_id": 436, + "package_id": 445, }, }, "depth": 1, @@ -22520,11 +22772,11 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "debug": { "id": 51, - "package_id": 429, + "package_id": 432, }, "semver": { "id": 55, - "package_id": 430, + "package_id": 433, }, }, "depth": 1, @@ -22535,7 +22787,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "glob-parent": { "id": 176, - "package_id": 433, + "package_id": 439, }, }, "depth": 1, @@ -22546,7 +22798,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "glob-parent": { "id": 424, - "package_id": 433, + "package_id": 446, }, }, "depth": 1, @@ -22557,7 +22809,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "lilconfig": { "id": 619, - "package_id": 440, + "package_id": 450, }, }, "depth": 1, @@ -22568,7 +22820,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "minimatch": { "id": 462, - "package_id": 437, + "package_id": 447, }, }, "depth": 1, @@ -22579,11 +22831,11 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "minimatch": { "id": 79, - "package_id": 432, + "package_id": 436, }, "semver": { "id": 80, - "package_id": 430, + "package_id": 437, }, }, "depth": 1, @@ -22594,7 +22846,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "debug": { "id": 355, - "package_id": 434, + "package_id": 441, }, }, "depth": 1, @@ -22605,7 +22857,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "lru-cache": { "id": 865, - "package_id": 448, + "package_id": 459, }, }, "depth": 2, @@ -22616,7 +22868,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "glob": { "id": 667, - "package_id": 441, + "package_id": 451, }, }, "depth": 1, @@ -22627,7 +22879,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "brace-expansion": { "id": 881, - "package_id": 449, + "package_id": 462, }, }, "depth": 2, @@ -22638,7 +22890,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "lru-cache": { "id": 606, - "package_id": 439, + "package_id": 449, }, }, "depth": 1, @@ -22649,7 +22901,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "brace-expansion": { "id": 868, - "package_id": 449, + "package_id": 460, }, }, "depth": 2, @@ -22659,8 +22911,8 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "dependencies": { "lru-cache": { - "id": 865, - "package_id": 448, + "id": 869, + "package_id": 461, }, }, "depth": 2, @@ -22671,7 +22923,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "@types/node": { "id": 65, - "package_id": 431, + "package_id": 435, }, }, "depth": 1, @@ -22682,7 +22934,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "emoji-regex": { "id": 701, - "package_id": 442, + "package_id": 452, }, }, "depth": 1, @@ -22693,15 +22945,15 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "string-width": { "id": 35, - "package_id": 426, + "package_id": 429, }, "strip-ansi": { "id": 37, - "package_id": 427, + "package_id": 430, }, "wrap-ansi": { "id": 39, - "package_id": 428, + "package_id": 431, }, }, "depth": 1, @@ -22712,7 +22964,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "chalk": { "id": 17, - "package_id": 425, + "package_id": 428, }, }, "depth": 1, @@ -22722,8 +22974,8 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` { "dependencies": { "emoji-regex": { - "id": 701, - "package_id": 442, + "id": 704, + "package_id": 453, }, }, "depth": 1, @@ -22734,7 +22986,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "ansi-regex": { "id": 860, - "package_id": 446, + "package_id": 457, }, }, "depth": 2, @@ -22745,7 +22997,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "ansi-styles": { "id": 861, - "package_id": 447, + "package_id": 458, }, }, "depth": 2, @@ -22756,15 +23008,15 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "ansi-styles": { "id": 854, - "package_id": 443, + "package_id": 454, }, "escape-string-regexp": { "id": 855, - "package_id": 444, + "package_id": 455, }, "supports-color": { "id": 856, - "package_id": 445, + "package_id": 456, }, }, "depth": 2, @@ -22775,7 +23027,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "color-convert": { "id": 891, - "package_id": 450, + "package_id": 463, }, }, "depth": 3, @@ -22786,7 +23038,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "has-flag": { "id": 892, - "package_id": 451, + "package_id": 464, }, }, "depth": 3, @@ -22797,7 +23049,7 @@ exports[`hot reloading works on the client (+ tailwind hmr) 1`] = ` "dependencies": { "color-name": { "id": 897, - "package_id": 452, + "package_id": 465, }, }, "depth": 4, diff --git a/test/integration/next-pages/test/__snapshots__/next-build.test.ts.snap b/test/integration/next-pages/test/__snapshots__/next-build.test.ts.snap index d64c703ce138ef..2fa624a519a12e 100644 --- a/test/integration/next-pages/test/__snapshots__/next-build.test.ts.snap +++ b/test/integration/next-pages/test/__snapshots__/next-build.test.ts.snap @@ -170,7 +170,7 @@ exports[`next build works: bun 1`] = ` "name": "tailwindcss", "version": "==3.3.3", }, - "package_id": 379, + "package_id": 381, }, { "behavior": { @@ -183,7 +183,7 @@ exports[`next build works: bun 1`] = ` "name": "typescript", "version": "==5.2.2", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -235,7 +235,7 @@ exports[`next build works: bun 1`] = ` "name": "chalk", "version": ">=2.4.2 <3.0.0", }, - "package_id": 425, + "package_id": 428, }, { "behavior": { @@ -417,7 +417,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-json-comments", "version": ">=3.1.1 <4.0.0", }, - "package_id": 374, + "package_id": 376, }, { "behavior": { @@ -469,7 +469,7 @@ exports[`next build works: bun 1`] = ` "name": "string-width", "version": ">=5.1.2 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -483,7 +483,7 @@ exports[`next build works: bun 1`] = ` "name": "string-width", "version": ">=4.2.0 <5.0.0", }, - "package_id": 367, + "package_id": 368, }, { "behavior": { @@ -496,7 +496,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -510,7 +510,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 374, }, { "behavior": { @@ -523,7 +523,7 @@ exports[`next build works: bun 1`] = ` "name": "wrap-ansi", "version": ">=8.1.0 <9.0.0", }, - "package_id": 428, + "package_id": 431, }, { "behavior": { @@ -537,7 +537,7 @@ exports[`next build works: bun 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 417, }, { "behavior": { @@ -680,7 +680,7 @@ exports[`next build works: bun 1`] = ` "name": "debug", "version": "==4.3.4", }, - "package_id": 429, + "package_id": 432, }, { "behavior": { @@ -732,7 +732,7 @@ exports[`next build works: bun 1`] = ` "name": "semver", "version": "==7.6.0", }, - "package_id": 430, + "package_id": 433, }, { "behavior": { @@ -745,7 +745,7 @@ exports[`next build works: bun 1`] = ` "name": "tar-fs", "version": "==3.0.5", }, - "package_id": 381, + "package_id": 383, }, { "behavior": { @@ -758,7 +758,7 @@ exports[`next build works: bun 1`] = ` "name": "unbzip2-stream", "version": "==1.4.3", }, - "package_id": 401, + "package_id": 403, }, { "behavior": { @@ -771,7 +771,7 @@ exports[`next build works: bun 1`] = ` "name": "yargs", "version": "==17.7.2", }, - "package_id": 420, + "package_id": 423, }, { "behavior": { @@ -784,7 +784,7 @@ exports[`next build works: bun 1`] = ` "name": "tslib", "version": ">=2.4.0 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -849,7 +849,7 @@ exports[`next build works: bun 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 434, }, { "behavior": { @@ -862,7 +862,7 @@ exports[`next build works: bun 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 435, }, { "behavior": { @@ -1044,7 +1044,7 @@ exports[`next build works: bun 1`] = ` "name": "minimatch", "version": "==9.0.3", }, - "package_id": 432, + "package_id": 436, }, { "behavior": { @@ -1057,7 +1057,7 @@ exports[`next build works: bun 1`] = ` "name": "semver", "version": ">=7.5.4 <8.0.0", }, - "package_id": 430, + "package_id": 437, }, { "behavior": { @@ -1070,7 +1070,7 @@ exports[`next build works: bun 1`] = ` "name": "ts-api-utils", "version": ">=1.0.1 <2.0.0", }, - "package_id": 389, + "package_id": 391, }, { "behavior": { @@ -1174,7 +1174,7 @@ exports[`next build works: bun 1`] = ` "name": "uri-js", "version": ">=4.2.2 <5.0.0", }, - "package_id": 405, + "package_id": 407, }, { "behavior": { @@ -1824,7 +1824,7 @@ exports[`next build works: bun 1`] = ` "name": "tslib", "version": ">=2.0.1 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -2097,7 +2097,7 @@ exports[`next build works: bun 1`] = ` "name": "update-browserslist-db", "version": ">=1.0.13 <2.0.0", }, - "package_id": 404, + "package_id": 406, }, { "behavior": { @@ -2136,7 +2136,7 @@ exports[`next build works: bun 1`] = ` "name": "@types/node", "version": ">=20.12.8 <20.13.0", }, - "package_id": 431, + "package_id": 438, }, { "behavior": { @@ -2253,7 +2253,7 @@ exports[`next build works: bun 1`] = ` "name": "supports-color", "version": ">=7.1.0 <8.0.0", }, - "package_id": 377, + "package_id": 379, }, { "behavior": { @@ -2305,7 +2305,7 @@ exports[`next build works: bun 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <5.2.0", }, - "package_id": 433, + "package_id": 439, }, { "behavior": { @@ -2396,7 +2396,7 @@ exports[`next build works: bun 1`] = ` "name": "urlpattern-polyfill", "version": "==10.0.0", }, - "package_id": 406, + "package_id": 408, }, { "behavior": { @@ -2409,7 +2409,7 @@ exports[`next build works: bun 1`] = ` "name": "zod", "version": "==3.23.8", }, - "package_id": 424, + "package_id": 427, }, { "behavior": { @@ -2435,7 +2435,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -2448,7 +2448,7 @@ exports[`next build works: bun 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 416, }, { "behavior": { @@ -2475,7 +2475,7 @@ exports[`next build works: bun 1`] = ` "name": "typescript", "version": ">=4.9.5", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -2566,7 +2566,7 @@ exports[`next build works: bun 1`] = ` "name": "which", "version": ">=2.0.1 <3.0.0", }, - "package_id": 408, + "package_id": 410, }, { "behavior": { @@ -2878,7 +2878,7 @@ exports[`next build works: bun 1`] = ` "name": "tapable", "version": ">=2.2.0 <3.0.0", }, - "package_id": 380, + "package_id": 382, }, { "behavior": { @@ -3385,7 +3385,7 @@ exports[`next build works: bun 1`] = ` "name": "string.prototype.trim", "version": ">=1.2.9 <2.0.0", }, - "package_id": 369, + "package_id": 370, }, { "behavior": { @@ -3398,7 +3398,7 @@ exports[`next build works: bun 1`] = ` "name": "string.prototype.trimend", "version": ">=1.0.8 <2.0.0", }, - "package_id": 370, + "package_id": 371, }, { "behavior": { @@ -3411,7 +3411,7 @@ exports[`next build works: bun 1`] = ` "name": "string.prototype.trimstart", "version": ">=1.0.8 <2.0.0", }, - "package_id": 371, + "package_id": 372, }, { "behavior": { @@ -3424,7 +3424,7 @@ exports[`next build works: bun 1`] = ` "name": "typed-array-buffer", "version": ">=1.0.2 <2.0.0", }, - "package_id": 395, + "package_id": 397, }, { "behavior": { @@ -3437,7 +3437,7 @@ exports[`next build works: bun 1`] = ` "name": "typed-array-byte-length", "version": ">=1.0.1 <2.0.0", }, - "package_id": 396, + "package_id": 398, }, { "behavior": { @@ -3450,7 +3450,7 @@ exports[`next build works: bun 1`] = ` "name": "typed-array-byte-offset", "version": ">=1.0.2 <2.0.0", }, - "package_id": 397, + "package_id": 399, }, { "behavior": { @@ -3463,7 +3463,7 @@ exports[`next build works: bun 1`] = ` "name": "typed-array-length", "version": ">=1.0.6 <2.0.0", }, - "package_id": 398, + "package_id": 400, }, { "behavior": { @@ -3476,7 +3476,7 @@ exports[`next build works: bun 1`] = ` "name": "unbox-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 400, + "package_id": 402, }, { "behavior": { @@ -3489,7 +3489,7 @@ exports[`next build works: bun 1`] = ` "name": "which-typed-array", "version": ">=1.1.15 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -4308,7 +4308,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -4321,7 +4321,7 @@ exports[`next build works: bun 1`] = ` "name": "text-table", "version": ">=0.2.0 <0.3.0", }, - "package_id": 384, + "package_id": 386, }, { "behavior": { @@ -4348,7 +4348,7 @@ exports[`next build works: bun 1`] = ` "name": "typescript", "version": ">=3.3.1", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -4478,7 +4478,7 @@ exports[`next build works: bun 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 440, }, { "behavior": { @@ -4634,7 +4634,7 @@ exports[`next build works: bun 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 441, }, { "behavior": { @@ -4712,7 +4712,7 @@ exports[`next build works: bun 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 442, }, { "behavior": { @@ -4725,7 +4725,7 @@ exports[`next build works: bun 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 443, }, { "behavior": { @@ -4868,7 +4868,7 @@ exports[`next build works: bun 1`] = ` "name": "tsconfig-paths", "version": ">=3.15.0 <4.0.0", }, - "package_id": 391, + "package_id": 393, }, { "behavior": { @@ -5180,7 +5180,7 @@ exports[`next build works: bun 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 444, }, { "behavior": { @@ -5310,7 +5310,7 @@ exports[`next build works: bun 1`] = ` "name": "resolve", "version": ">=2.0.0-next.5 <3.0.0", }, - "package_id": 436, + "package_id": 445, }, { "behavior": { @@ -5336,7 +5336,7 @@ exports[`next build works: bun 1`] = ` "name": "string.prototype.matchall", "version": ">=4.0.11 <5.0.0", }, - "package_id": 368, + "package_id": 369, }, { "behavior": { @@ -5492,7 +5492,7 @@ exports[`next build works: bun 1`] = ` "name": "yauzl", "version": ">=2.10.0 <3.0.0", }, - "package_id": 422, + "package_id": 425, }, { "behavior": { @@ -5531,7 +5531,7 @@ exports[`next build works: bun 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <6.0.0", }, - "package_id": 433, + "package_id": 446, }, { "behavior": { @@ -5609,7 +5609,7 @@ exports[`next build works: bun 1`] = ` "name": "to-regex-range", "version": ">=5.0.1 <6.0.0", }, - "package_id": 388, + "package_id": 390, }, { "behavior": { @@ -5752,7 +5752,7 @@ exports[`next build works: bun 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -6025,7 +6025,7 @@ exports[`next build works: bun 1`] = ` "name": "minimatch", "version": ">=9.0.1 <10.0.0", }, - "package_id": 437, + "package_id": 447, }, { "behavior": { @@ -6077,7 +6077,7 @@ exports[`next build works: bun 1`] = ` "name": "type-fest", "version": ">=0.20.2 <0.21.0", }, - "package_id": 394, + "package_id": 396, }, { "behavior": { @@ -6337,7 +6337,7 @@ exports[`next build works: bun 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -6662,7 +6662,7 @@ exports[`next build works: bun 1`] = ` "name": "which-typed-array", "version": ">=1.1.14 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -6844,7 +6844,7 @@ exports[`next build works: bun 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -6948,7 +6948,7 @@ exports[`next build works: bun 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -7052,7 +7052,7 @@ exports[`next build works: bun 1`] = ` "name": "thenify-all", "version": ">=1.0.0 <2.0.0", }, - "package_id": 386, + "package_id": 388, }, { "behavior": { @@ -7301,7 +7301,7 @@ exports[`next build works: bun 1`] = ` "name": "postcss", "version": "==8.4.31", }, - "package_id": 438, + "package_id": 448, }, { "behavior": { @@ -7314,7 +7314,7 @@ exports[`next build works: bun 1`] = ` "name": "styled-jsx", "version": "==5.1.1", }, - "package_id": 375, + "package_id": 377, }, { "behavior": { @@ -7587,7 +7587,7 @@ exports[`next build works: bun 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -7652,7 +7652,7 @@ exports[`next build works: bun 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -7665,7 +7665,7 @@ exports[`next build works: bun 1`] = ` "name": "word-wrap", "version": ">=1.2.5 <2.0.0", }, - "package_id": 413, + "package_id": 415, }, { "behavior": { @@ -7678,7 +7678,7 @@ exports[`next build works: bun 1`] = ` "name": "yocto-queue", "version": ">=0.1.0 <0.2.0", }, - "package_id": 423, + "package_id": 426, }, { "behavior": { @@ -7899,7 +7899,7 @@ exports[`next build works: bun 1`] = ` "name": "lru-cache", "version": ">=10.2.0 <11.0.0", }, - "package_id": 439, + "package_id": 449, }, { "behavior": { @@ -8070,7 +8070,7 @@ exports[`next build works: bun 1`] = ` "name": "lilconfig", "version": ">=3.0.0 <4.0.0", }, - "package_id": 440, + "package_id": 450, }, { "behavior": { @@ -8083,7 +8083,7 @@ exports[`next build works: bun 1`] = ` "name": "yaml", "version": ">=2.3.4 <3.0.0", }, - "package_id": 419, + "package_id": 422, }, { "behavior": { @@ -8135,7 +8135,7 @@ exports[`next build works: bun 1`] = ` "name": "util-deprecate", "version": ">=1.0.2 <2.0.0", }, - "package_id": 407, + "package_id": 409, }, { "behavior": { @@ -8421,7 +8421,7 @@ exports[`next build works: bun 1`] = ` "name": "ws", "version": "==8.17.1", }, - "package_id": 416, + "package_id": 419, }, { "behavior": { @@ -8590,7 +8590,7 @@ exports[`next build works: bun 1`] = ` "name": "which-builtin-type", "version": ">=1.1.3 <2.0.0", }, - "package_id": 410, + "package_id": 412, }, { "behavior": { @@ -8681,7 +8681,7 @@ exports[`next build works: bun 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -8694,7 +8694,7 @@ exports[`next build works: bun 1`] = ` "name": "glob", "version": ">=7.1.3 <8.0.0", }, - "package_id": 441, + "package_id": 451, }, { "behavior": { @@ -9123,7 +9123,7 @@ exports[`next build works: bun 1`] = ` "name": "text-decoder", "version": ">=1.1.0 <2.0.0", }, - "package_id": 383, + "package_id": 385, }, { "behavior": { @@ -9136,7 +9136,7 @@ exports[`next build works: bun 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": 442, + "package_id": 452, }, { "behavior": { @@ -9162,7 +9162,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -9175,7 +9175,7 @@ exports[`next build works: bun 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": null, + "package_id": 453, }, { "behavior": { @@ -9188,7 +9188,7 @@ exports[`next build works: bun 1`] = ` "name": "is-fullwidth-code-point", "version": ">=3.0.0 <4.0.0", }, - "package_id": null, + "package_id": 228, }, { "behavior": { @@ -9201,7 +9201,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -9513,7 +9513,7 @@ exports[`next build works: bun 1`] = ` "name": "ansi-regex", "version": ">=5.0.1 <6.0.0", }, - "package_id": null, + "package_id": 55, }, { "behavior": { @@ -9630,7 +9630,7 @@ exports[`next build works: bun 1`] = ` "name": "ts-interface-checker", "version": ">=0.1.9 <0.2.0", }, - "package_id": 390, + "package_id": 392, }, { "behavior": { @@ -9929,7 +9929,7 @@ exports[`next build works: bun 1`] = ` "name": "sucrase", "version": ">=3.32.0 <4.0.0", }, - "package_id": 376, + "package_id": 378, }, { "behavior": { @@ -9981,7 +9981,7 @@ exports[`next build works: bun 1`] = ` "name": "tar-stream", "version": ">=3.1.5 <4.0.0", }, - "package_id": 382, + "package_id": 384, }, { "behavior": { @@ -10059,7 +10059,7 @@ exports[`next build works: bun 1`] = ` "name": "thenify", "version": ">=3.1.0 && <4.0.0", }, - "package_id": 385, + "package_id": 387, }, { "behavior": { @@ -10085,7 +10085,7 @@ exports[`next build works: bun 1`] = ` "name": "typescript", "version": ">=4.2.0", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -10137,7 +10137,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-bom", "version": ">=3.0.0 <4.0.0", }, - "package_id": 373, + "package_id": 375, }, { "behavior": { @@ -10462,7 +10462,7 @@ exports[`next build works: bun 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -10488,7 +10488,7 @@ exports[`next build works: bun 1`] = ` "name": "through", "version": ">=2.3.8 <3.0.0", }, - "package_id": 387, + "package_id": 389, }, { "behavior": { @@ -10748,7 +10748,7 @@ exports[`next build works: bun 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -10761,7 +10761,7 @@ exports[`next build works: bun 1`] = ` "name": "which-collection", "version": ">=1.0.1 <2.0.0", }, - "package_id": 411, + "package_id": 413, }, { "behavior": { @@ -10774,7 +10774,7 @@ exports[`next build works: bun 1`] = ` "name": "which-typed-array", "version": ">=1.1.9 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -10930,7 +10930,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -10943,7 +10943,7 @@ exports[`next build works: bun 1`] = ` "name": "ansi-styles", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 56, }, { "behavior": { @@ -10956,7 +10956,7 @@ exports[`next build works: bun 1`] = ` "name": "string-width", "version": ">=4.1.0 <5.0.0", }, - "package_id": null, + "package_id": 367, }, { "behavior": { @@ -10969,7 +10969,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -11075,7 +11075,7 @@ exports[`next build works: bun 1`] = ` "name": "y18n", "version": ">=5.0.5 <6.0.0", }, - "package_id": 417, + "package_id": 420, }, { "behavior": { @@ -11088,7 +11088,7 @@ exports[`next build works: bun 1`] = ` "name": "yargs-parser", "version": ">=21.1.1 <22.0.0", }, - "package_id": 421, + "package_id": 424, }, { "behavior": { @@ -11127,7 +11127,7 @@ exports[`next build works: bun 1`] = ` "name": "ansi-styles", "version": ">=3.2.1 <4.0.0", }, - "package_id": 443, + "package_id": 454, }, { "behavior": { @@ -11140,7 +11140,7 @@ exports[`next build works: bun 1`] = ` "name": "escape-string-regexp", "version": ">=1.0.5 <2.0.0", }, - "package_id": 444, + "package_id": 455, }, { "behavior": { @@ -11153,7 +11153,7 @@ exports[`next build works: bun 1`] = ` "name": "supports-color", "version": ">=5.3.0 <6.0.0", }, - "package_id": 445, + "package_id": 456, }, { "behavior": { @@ -11192,7 +11192,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -11205,7 +11205,7 @@ exports[`next build works: bun 1`] = ` "name": "ansi-regex", "version": ">=6.0.1 <7.0.0", }, - "package_id": 446, + "package_id": 457, }, { "behavior": { @@ -11218,7 +11218,7 @@ exports[`next build works: bun 1`] = ` "name": "ansi-styles", "version": ">=6.1.0 <7.0.0", }, - "package_id": 447, + "package_id": 458, }, { "behavior": { @@ -11231,7 +11231,7 @@ exports[`next build works: bun 1`] = ` "name": "string-width", "version": ">=5.0.1 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -11244,7 +11244,7 @@ exports[`next build works: bun 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -11270,7 +11270,7 @@ exports[`next build works: bun 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": 448, + "package_id": 459, }, { "behavior": { @@ -11283,7 +11283,7 @@ exports[`next build works: bun 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": 402, + "package_id": 404, }, { "behavior": { @@ -11296,7 +11296,7 @@ exports[`next build works: bun 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -11309,7 +11309,7 @@ exports[`next build works: bun 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 460, }, { "behavior": { @@ -11322,7 +11322,7 @@ exports[`next build works: bun 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 461, }, { "behavior": { @@ -11335,7 +11335,7 @@ exports[`next build works: bun 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -11374,7 +11374,7 @@ exports[`next build works: bun 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -11387,7 +11387,7 @@ exports[`next build works: bun 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -11413,7 +11413,7 @@ exports[`next build works: bun 1`] = ` "name": "esutils", "version": ">=2.0.2 <3.0.0", }, - "package_id": null, + "package_id": 162, }, { "behavior": { @@ -11452,7 +11452,7 @@ exports[`next build works: bun 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -11465,7 +11465,7 @@ exports[`next build works: bun 1`] = ` "name": "is-glob", "version": ">=4.0.1 <5.0.0", }, - "package_id": null, + "package_id": 230, }, { "behavior": { @@ -11478,7 +11478,7 @@ exports[`next build works: bun 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 462, }, { "behavior": { @@ -11608,7 +11608,7 @@ exports[`next build works: bun 1`] = ` "name": "color-convert", "version": ">=1.9.0 <2.0.0", }, - "package_id": 450, + "package_id": 463, }, { "behavior": { @@ -11621,7 +11621,7 @@ exports[`next build works: bun 1`] = ` "name": "has-flag", "version": ">=3.0.0 <4.0.0", }, - "package_id": 451, + "package_id": 464, }, { "behavior": { @@ -11634,7 +11634,7 @@ exports[`next build works: bun 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": 418, + "package_id": 421, }, { "behavior": { @@ -11660,7 +11660,7 @@ exports[`next build works: bun 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 421, }, { "behavior": { @@ -11673,7 +11673,7 @@ exports[`next build works: bun 1`] = ` "name": "balanced-match", "version": ">=1.0.0 <2.0.0", }, - "package_id": null, + "package_id": 79, }, { "behavior": { @@ -11686,7 +11686,7 @@ exports[`next build works: bun 1`] = ` "name": "color-name", "version": "==1.1.3", }, - "package_id": 452, + "package_id": 465, }, ], "format": "v2", @@ -11731,7 +11731,9 @@ exports[`next build works: bun 1`] = ` "@tootallnate/quickjs-emscripten": 37, "@types/json5": 38, "@types/node": [ - 431, + 434, + 435, + 438, 39, ], "@types/prop-types": 40, @@ -11750,13 +11752,13 @@ exports[`next build works: bun 1`] = ` "agent-base": 53, "ajv": 54, "ansi-regex": [ - 446, + 457, 55, ], "ansi-styles": [ - 447, + 458, 56, - 443, + 454, ], "any-promise": 57, "anymatch": 58, @@ -11790,7 +11792,8 @@ exports[`next build works: bun 1`] = ` "basic-ftp": 86, "binary-extensions": 87, "brace-expansion": [ - 449, + 460, + 462, 88, ], "braces": 89, @@ -11805,7 +11808,7 @@ exports[`next build works: bun 1`] = ` "caniuse-lite": 98, "chalk": [ 99, - 425, + 428, ], "chokidar": 100, "chromium-bidi": 101, @@ -11813,11 +11816,11 @@ exports[`next build works: bun 1`] = ` "cliui": 103, "color-convert": [ 104, - 450, + 463, ], "color-name": [ 105, - 452, + 465, ], "commander": 106, "concat-map": 107, @@ -11832,8 +11835,10 @@ exports[`next build works: bun 1`] = ` "data-view-byte-offset": 116, "debug": [ 117, - 429, - 434, + 432, + 440, + 441, + 442, ], "deep-is": 118, "default-create-template": 0, @@ -11847,13 +11852,15 @@ exports[`next build works: bun 1`] = ` "dlv": 126, "doctrine": [ 127, - 435, + 443, + 444, ], "eastasianwidth": 128, "electron-to-chromium": 129, "emoji-regex": [ 130, - 442, + 452, + 453, ], "end-of-stream": 131, "enhanced-resolve": 132, @@ -11870,7 +11877,7 @@ exports[`next build works: bun 1`] = ` "escalade": 143, "escape-string-regexp": [ 144, - 444, + 455, ], "escodegen": 145, "eslint": 146, @@ -11920,11 +11927,12 @@ exports[`next build works: bun 1`] = ` "get-uri": 190, "glob": [ 191, - 441, + 451, ], "glob-parent": [ 192, - 433, + 439, + 446, ], "globals": 193, "globalthis": 194, @@ -11935,7 +11943,7 @@ exports[`next build works: bun 1`] = ` "has-bigints": 199, "has-flag": [ 200, - 451, + 464, ], "has-property-descriptors": 201, "has-proto": 202, @@ -12001,7 +12009,7 @@ exports[`next build works: bun 1`] = ` "language-tags": 262, "levn": 263, "lilconfig": [ - 440, + 450, 264, ], "lines-and-columns": 265, @@ -12009,15 +12017,16 @@ exports[`next build works: bun 1`] = ` "lodash.merge": 267, "loose-envify": 268, "lru-cache": [ - 439, + 449, 269, - 448, + 459, + 461, ], "merge2": 270, "micromatch": 271, "minimatch": [ - 437, - 432, + 447, + 436, 272, ], "minimist": 273, @@ -12063,7 +12072,7 @@ exports[`next build works: bun 1`] = ` "pirates": 313, "possible-typed-array-names": 314, "postcss": [ - 438, + 448, 315, ], "postcss-import": 316, @@ -12093,7 +12102,7 @@ exports[`next build works: bun 1`] = ` "regexp.prototype.flags": 340, "require-directory": 341, "resolve": [ - 436, + 445, 342, ], "resolve-from": 343, @@ -12105,7 +12114,8 @@ exports[`next build works: bun 1`] = ` "safe-regex-test": 349, "scheduler": 350, "semver": [ - 430, + 433, + 437, 351, ], "set-function-length": 352, @@ -12124,75 +12134,78 @@ exports[`next build works: bun 1`] = ` "streamsearch": 365, "streamx": 366, "string-width": [ - 426, + 429, 367, + 368, ], - "string.prototype.matchall": 368, - "string.prototype.trim": 369, - "string.prototype.trimend": 370, - "string.prototype.trimstart": 371, + "string.prototype.matchall": 369, + "string.prototype.trim": 370, + "string.prototype.trimend": 371, + "string.prototype.trimstart": 372, "strip-ansi": [ - 427, - 372, + 430, + 373, + 374, ], - "strip-bom": 373, - "strip-json-comments": 374, - "styled-jsx": 375, - "sucrase": 376, + "strip-bom": 375, + "strip-json-comments": 376, + "styled-jsx": 377, + "sucrase": 378, "supports-color": [ - 377, - 445, + 379, + 456, ], - "supports-preserve-symlinks-flag": 378, - "tailwindcss": 379, - "tapable": 380, - "tar-fs": 381, - "tar-stream": 382, - "text-decoder": 383, - "text-table": 384, - "thenify": 385, - "thenify-all": 386, - "through": 387, - "to-regex-range": 388, - "ts-api-utils": 389, - "ts-interface-checker": 390, - "tsconfig-paths": 391, - "tslib": 392, - "type-check": 393, - "type-fest": 394, - "typed-array-buffer": 395, - "typed-array-byte-length": 396, - "typed-array-byte-offset": 397, - "typed-array-length": 398, - "typescript": 399, - "unbox-primitive": 400, - "unbzip2-stream": 401, - "undici-types": 402, - "universalify": 403, - "update-browserslist-db": 404, - "uri-js": 405, - "urlpattern-polyfill": 406, - "util-deprecate": 407, - "which": 408, - "which-boxed-primitive": 409, - "which-builtin-type": 410, - "which-collection": 411, - "which-typed-array": 412, - "word-wrap": 413, + "supports-preserve-symlinks-flag": 380, + "tailwindcss": 381, + "tapable": 382, + "tar-fs": 383, + "tar-stream": 384, + "text-decoder": 385, + "text-table": 386, + "thenify": 387, + "thenify-all": 388, + "through": 389, + "to-regex-range": 390, + "ts-api-utils": 391, + "ts-interface-checker": 392, + "tsconfig-paths": 393, + "tslib": 394, + "type-check": 395, + "type-fest": 396, + "typed-array-buffer": 397, + "typed-array-byte-length": 398, + "typed-array-byte-offset": 399, + "typed-array-length": 400, + "typescript": 401, + "unbox-primitive": 402, + "unbzip2-stream": 403, + "undici-types": 404, + "universalify": 405, + "update-browserslist-db": 406, + "uri-js": 407, + "urlpattern-polyfill": 408, + "util-deprecate": 409, + "which": 410, + "which-boxed-primitive": 411, + "which-builtin-type": 412, + "which-collection": 413, + "which-typed-array": 414, + "word-wrap": 415, "wrap-ansi": [ - 428, - 414, + 431, + 416, + 417, ], - "wrappy": 415, - "ws": 416, - "y18n": 417, - "yallist": 418, - "yaml": 419, - "yargs": 420, - "yargs-parser": 421, - "yauzl": 422, - "yocto-queue": 423, - "zod": 424, + "wrappy": 418, + "ws": 419, + "y18n": 420, + "yallist": 421, + "yaml": 422, + "yargs": 423, + "yargs-parser": 424, + "yauzl": 425, + "yocto-queue": 426, + "zod": 427, }, "packages": [ { @@ -19108,6 +19121,26 @@ exports[`next build works: bun 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 704, + 705, + 706, + ], + "id": 368, + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "man_dir": "", + "name": "string-width", + "name_hash": "15727733666069179645", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "tag": "npm", + "value": "4.2.3", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ @@ -19124,7 +19157,7 @@ exports[`next build works: bun 1`] = ` 717, 718, ], - "id": 368, + "id": 369, "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "man_dir": "", "name": "string.prototype.matchall", @@ -19145,7 +19178,7 @@ exports[`next build works: bun 1`] = ` 721, 722, ], - "id": 369, + "id": 370, "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "man_dir": "", "name": "string.prototype.trim", @@ -19165,7 +19198,7 @@ exports[`next build works: bun 1`] = ` 724, 725, ], - "id": 370, + "id": 371, "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "man_dir": "", "name": "string.prototype.trimend", @@ -19185,7 +19218,7 @@ exports[`next build works: bun 1`] = ` 727, 728, ], - "id": 371, + "id": 372, "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "man_dir": "", "name": "string.prototype.trimstart", @@ -19203,7 +19236,25 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 729, ], - "id": 372, + "id": 373, + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "man_dir": "", + "name": "strip-ansi", + "name_hash": "13340235767065158173", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "tag": "npm", + "value": "6.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 730, + ], + "id": 374, "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "man_dir": "", "name": "strip-ansi", @@ -19219,7 +19270,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 373, + "id": 375, "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "man_dir": "", "name": "strip-bom", @@ -19235,7 +19286,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 374, + "id": 376, "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "man_dir": "", "name": "strip-json-comments", @@ -19254,7 +19305,7 @@ exports[`next build works: bun 1`] = ` 731, 732, ], - "id": 375, + "id": 377, "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", "man_dir": "", "name": "styled-jsx", @@ -19281,7 +19332,7 @@ exports[`next build works: bun 1`] = ` 738, 739, ], - "id": 376, + "id": 378, "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "man_dir": "", "name": "sucrase", @@ -19299,7 +19350,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 740, ], - "id": 377, + "id": 379, "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "man_dir": "", "name": "supports-color", @@ -19315,7 +19366,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 378, + "id": 380, "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "man_dir": "", "name": "supports-preserve-symlinks-flag", @@ -19357,7 +19408,7 @@ exports[`next build works: bun 1`] = ` 761, 762, ], - "id": 379, + "id": 381, "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", "man_dir": "", "name": "tailwindcss", @@ -19373,7 +19424,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 380, + "id": 382, "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "man_dir": "", "name": "tapable", @@ -19394,7 +19445,7 @@ exports[`next build works: bun 1`] = ` 765, 766, ], - "id": 381, + "id": 383, "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", "man_dir": "", "name": "tar-fs", @@ -19414,7 +19465,7 @@ exports[`next build works: bun 1`] = ` 768, 769, ], - "id": 382, + "id": 384, "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "man_dir": "", "name": "tar-stream", @@ -19432,7 +19483,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 770, ], - "id": 383, + "id": 385, "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", "man_dir": "", "name": "text-decoder", @@ -19448,7 +19499,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 384, + "id": 386, "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "man_dir": "", "name": "text-table", @@ -19466,7 +19517,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 771, ], - "id": 385, + "id": 387, "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "man_dir": "", "name": "thenify", @@ -19484,7 +19535,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 772, ], - "id": 386, + "id": 388, "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "man_dir": "", "name": "thenify-all", @@ -19500,7 +19551,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 387, + "id": 389, "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "man_dir": "", "name": "through", @@ -19518,7 +19569,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 773, ], - "id": 388, + "id": 390, "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "man_dir": "", "name": "to-regex-range", @@ -19536,7 +19587,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 774, ], - "id": 389, + "id": 391, "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "man_dir": "", "name": "ts-api-utils", @@ -19552,7 +19603,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 390, + "id": 392, "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "man_dir": "", "name": "ts-interface-checker", @@ -19573,7 +19624,7 @@ exports[`next build works: bun 1`] = ` 777, 778, ], - "id": 391, + "id": 393, "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "man_dir": "", "name": "tsconfig-paths", @@ -19589,7 +19640,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 392, + "id": 394, "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "man_dir": "", "name": "tslib", @@ -19607,7 +19658,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 779, ], - "id": 393, + "id": 395, "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "man_dir": "", "name": "type-check", @@ -19623,7 +19674,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 394, + "id": 396, "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "man_dir": "", "name": "type-fest", @@ -19643,7 +19694,7 @@ exports[`next build works: bun 1`] = ` 781, 782, ], - "id": 395, + "id": 397, "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "man_dir": "", "name": "typed-array-buffer", @@ -19665,7 +19716,7 @@ exports[`next build works: bun 1`] = ` 786, 787, ], - "id": 396, + "id": 398, "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "man_dir": "", "name": "typed-array-byte-length", @@ -19688,7 +19739,7 @@ exports[`next build works: bun 1`] = ` 792, 793, ], - "id": 397, + "id": 399, "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "man_dir": "", "name": "typed-array-byte-offset", @@ -19711,7 +19762,7 @@ exports[`next build works: bun 1`] = ` 798, 799, ], - "id": 398, + "id": 400, "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "man_dir": "", "name": "typed-array-length", @@ -19730,7 +19781,7 @@ exports[`next build works: bun 1`] = ` "tsserver": "bin/tsserver", }, "dependencies": [], - "id": 399, + "id": 401, "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "man_dir": "", "name": "typescript", @@ -19751,7 +19802,7 @@ exports[`next build works: bun 1`] = ` 802, 803, ], - "id": 400, + "id": 402, "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "man_dir": "", "name": "unbox-primitive", @@ -19770,7 +19821,7 @@ exports[`next build works: bun 1`] = ` 804, 805, ], - "id": 401, + "id": 403, "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "man_dir": "", "name": "unbzip2-stream", @@ -19786,7 +19837,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 402, + "id": 404, "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "man_dir": "", "name": "undici-types", @@ -19802,7 +19853,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 403, + "id": 405, "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "man_dir": "", "name": "universalify", @@ -19825,7 +19876,7 @@ exports[`next build works: bun 1`] = ` 807, 808, ], - "id": 404, + "id": 406, "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "man_dir": "", "name": "update-browserslist-db", @@ -19843,7 +19894,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 809, ], - "id": 405, + "id": 407, "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "man_dir": "", "name": "uri-js", @@ -19859,7 +19910,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 406, + "id": 408, "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", "man_dir": "", "name": "urlpattern-polyfill", @@ -19875,7 +19926,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 407, + "id": 409, "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "man_dir": "", "name": "util-deprecate", @@ -19896,7 +19947,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 810, ], - "id": 408, + "id": 410, "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "man_dir": "", "name": "which", @@ -19918,7 +19969,7 @@ exports[`next build works: bun 1`] = ` 814, 815, ], - "id": 409, + "id": 411, "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "man_dir": "", "name": "which-boxed-primitive", @@ -19947,7 +19998,7 @@ exports[`next build works: bun 1`] = ` 826, 827, ], - "id": 410, + "id": 412, "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", "man_dir": "", "name": "which-builtin-type", @@ -19968,7 +20019,7 @@ exports[`next build works: bun 1`] = ` 830, 831, ], - "id": 411, + "id": 413, "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "man_dir": "", "name": "which-collection", @@ -19990,7 +20041,7 @@ exports[`next build works: bun 1`] = ` 835, 836, ], - "id": 412, + "id": 414, "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "man_dir": "", "name": "which-typed-array", @@ -20006,7 +20057,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 413, + "id": 415, "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "man_dir": "", "name": "word-wrap", @@ -20026,7 +20077,27 @@ exports[`next build works: bun 1`] = ` 838, 839, ], - "id": 414, + "id": 416, + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "man_dir": "", + "name": "wrap-ansi", + "name_hash": "6417752039399150421", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "tag": "npm", + "value": "7.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 840, + 841, + 842, + ], + "id": 417, "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "man_dir": "", "name": "wrap-ansi", @@ -20042,7 +20113,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 415, + "id": 418, "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "man_dir": "", "name": "wrappy", @@ -20061,7 +20132,7 @@ exports[`next build works: bun 1`] = ` 843, 844, ], - "id": 416, + "id": 419, "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "man_dir": "", "name": "ws", @@ -20077,7 +20148,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 417, + "id": 420, "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "man_dir": "", "name": "y18n", @@ -20093,7 +20164,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 418, + "id": 421, "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "man_dir": "", "name": "yallist", @@ -20112,7 +20183,7 @@ exports[`next build works: bun 1`] = ` "name": "yaml", }, "dependencies": [], - "id": 419, + "id": 422, "integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==", "man_dir": "", "name": "yaml", @@ -20136,7 +20207,7 @@ exports[`next build works: bun 1`] = ` 850, 851, ], - "id": 420, + "id": 423, "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "man_dir": "", "name": "yargs", @@ -20152,7 +20223,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 421, + "id": 424, "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "man_dir": "", "name": "yargs-parser", @@ -20171,7 +20242,7 @@ exports[`next build works: bun 1`] = ` 852, 853, ], - "id": 422, + "id": 425, "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "man_dir": "", "name": "yauzl", @@ -20187,7 +20258,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 423, + "id": 426, "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "man_dir": "", "name": "yocto-queue", @@ -20203,7 +20274,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 424, + "id": 427, "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "man_dir": "", "name": "zod", @@ -20223,7 +20294,7 @@ exports[`next build works: bun 1`] = ` 855, 856, ], - "id": 425, + "id": 428, "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "man_dir": "", "name": "chalk", @@ -20243,7 +20314,7 @@ exports[`next build works: bun 1`] = ` 858, 859, ], - "id": 426, + "id": 429, "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "man_dir": "", "name": "string-width", @@ -20261,7 +20332,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 860, ], - "id": 427, + "id": 430, "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "man_dir": "", "name": "strip-ansi", @@ -20281,7 +20352,7 @@ exports[`next build works: bun 1`] = ` 862, 863, ], - "id": 428, + "id": 431, "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "man_dir": "", "name": "wrap-ansi", @@ -20299,7 +20370,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 864, ], - "id": 429, + "id": 432, "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "man_dir": "", "name": "debug", @@ -20320,7 +20391,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 865, ], - "id": 430, + "id": 433, "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "man_dir": "", "name": "semver", @@ -20338,7 +20409,25 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 866, ], - "id": 431, + "id": 434, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 867, + ], + "id": 435, "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", "man_dir": "", "name": "@types/node", @@ -20356,7 +20445,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 868, ], - "id": 432, + "id": 436, "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "man_dir": "", "name": "minimatch", @@ -20369,12 +20458,51 @@ exports[`next build works: bun 1`] = ` }, "scripts": {}, }, + { + "bin": { + "file": "bin/semver.js", + "name": "semver", + }, + "dependencies": [ + 869, + ], + "id": 437, + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "man_dir": "", + "name": "semver", + "name_hash": "16367367531761322261", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "tag": "npm", + "value": "7.6.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 870, + ], + "id": 438, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ 871, ], - "id": 433, + "id": 439, "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "man_dir": "", "name": "glob-parent", @@ -20392,7 +20520,43 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 872, ], - "id": 434, + "id": 440, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 873, + ], + "id": 441, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 874, + ], + "id": 442, "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "man_dir": "", "name": "debug", @@ -20410,7 +20574,25 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 875, ], - "id": 435, + "id": 443, + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "man_dir": "", + "name": "doctrine", + "name_hash": "17204823894354646410", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "tag": "npm", + "value": "2.1.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 876, + ], + "id": 444, "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "man_dir": "", "name": "doctrine", @@ -20433,7 +20615,7 @@ exports[`next build works: bun 1`] = ` 878, 879, ], - "id": 436, + "id": 445, "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "man_dir": "", "name": "resolve", @@ -20446,12 +20628,30 @@ exports[`next build works: bun 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 880, + ], + "id": 446, + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "man_dir": "", + "name": "glob-parent", + "name_hash": "11965780159102682782", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "tag": "npm", + "value": "5.1.2", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ 881, ], - "id": 437, + "id": 447, "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "man_dir": "", "name": "minimatch", @@ -20471,7 +20671,7 @@ exports[`next build works: bun 1`] = ` 883, 884, ], - "id": 438, + "id": 448, "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "man_dir": "", "name": "postcss", @@ -20487,7 +20687,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 439, + "id": 449, "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "man_dir": "", "name": "lru-cache", @@ -20503,7 +20703,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 440, + "id": 450, "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "man_dir": "", "name": "lilconfig", @@ -20526,7 +20726,7 @@ exports[`next build works: bun 1`] = ` 889, 890, ], - "id": 441, + "id": 451, "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "man_dir": "", "name": "glob", @@ -20542,7 +20742,23 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 442, + "id": 452, + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "man_dir": "", + "name": "emoji-regex", + "name_hash": "4954026511424972012", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "tag": "npm", + "value": "8.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [], + "id": 453, "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "man_dir": "", "name": "emoji-regex", @@ -20560,7 +20776,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 891, ], - "id": 443, + "id": 454, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "man_dir": "", "name": "ansi-styles", @@ -20576,7 +20792,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 444, + "id": 455, "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "man_dir": "", "name": "escape-string-regexp", @@ -20594,7 +20810,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 892, ], - "id": 445, + "id": 456, "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "man_dir": "", "name": "supports-color", @@ -20610,7 +20826,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 446, + "id": 457, "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "man_dir": "", "name": "ansi-regex", @@ -20626,7 +20842,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 447, + "id": 458, "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "man_dir": "", "name": "ansi-styles", @@ -20644,7 +20860,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 893, ], - "id": 448, + "id": 459, "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "man_dir": "", "name": "lru-cache", @@ -20662,7 +20878,43 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 894, ], - "id": 449, + "id": 460, + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "man_dir": "", + "name": "brace-expansion", + "name_hash": "2949258092693339993", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "tag": "npm", + "value": "2.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 895, + ], + "id": 461, + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "man_dir": "", + "name": "lru-cache", + "name_hash": "15261810304153928944", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "tag": "npm", + "value": "6.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 896, + ], + "id": 462, "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "man_dir": "", "name": "brace-expansion", @@ -20680,7 +20932,7 @@ exports[`next build works: bun 1`] = ` "dependencies": [ 897, ], - "id": 450, + "id": 463, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "man_dir": "", "name": "color-convert", @@ -20696,7 +20948,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 451, + "id": 464, "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "man_dir": "", "name": "has-flag", @@ -20712,7 +20964,7 @@ exports[`next build works: bun 1`] = ` { "bin": null, "dependencies": [], - "id": 452, + "id": 465, "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "man_dir": "", "name": "color-name", @@ -22199,243 +22451,243 @@ exports[`next build works: bun 1`] = ` }, "string-width-cjs": { "id": 36, - "package_id": 367, + "package_id": 368, }, "string.prototype.matchall": { "id": 409, - "package_id": 368, + "package_id": 369, }, "string.prototype.trim": { "id": 259, - "package_id": 369, + "package_id": 370, }, "string.prototype.trimend": { "id": 260, - "package_id": 370, + "package_id": 371, }, "string.prototype.trimstart": { "id": 261, - "package_id": 371, + "package_id": 372, }, "strip-ansi": { "id": 330, - "package_id": 372, + "package_id": 373, }, "strip-ansi-cjs": { "id": 38, - "package_id": 372, + "package_id": 374, }, "strip-bom": { "id": 778, - "package_id": 373, + "package_id": 375, }, "strip-json-comments": { "id": 31, - "package_id": 374, + "package_id": 376, }, "styled-jsx": { "id": 561, - "package_id": 375, + "package_id": 377, }, "sucrase": { "id": 762, - "package_id": 376, + "package_id": 378, }, "supports-color": { "id": 172, - "package_id": 377, + "package_id": 379, }, "supports-preserve-symlinks-flag": { "id": 666, - "package_id": 378, + "package_id": 380, }, "tailwindcss": { "id": 12, - "package_id": 379, + "package_id": 381, }, "tapable": { "id": 220, - "package_id": 380, + "package_id": 382, }, "tar-fs": { "id": 56, - "package_id": 381, + "package_id": 383, }, "tar-stream": { "id": 766, - "package_id": 382, + "package_id": 384, }, "text-decoder": { "id": 700, - "package_id": 383, + "package_id": 385, }, "text-table": { "id": 331, - "package_id": 384, + "package_id": 386, }, "thenify": { "id": 772, - "package_id": 385, + "package_id": 387, }, "thenify-all": { "id": 541, - "package_id": 386, + "package_id": 388, }, "through": { "id": 805, - "package_id": 387, + "package_id": 389, }, "to-regex-range": { "id": 430, - "package_id": 388, + "package_id": 390, }, "ts-api-utils": { "id": 81, - "package_id": 389, + "package_id": 391, }, "ts-interface-checker": { "id": 739, - "package_id": 390, + "package_id": 392, }, "tsconfig-paths": { "id": 373, - "package_id": 391, + "package_id": 393, }, "tslib": { "id": 59, - "package_id": 392, + "package_id": 394, }, "type-check": { "id": 533, - "package_id": 393, + "package_id": 395, }, "type-fest": { "id": 466, - "package_id": 394, + "package_id": 396, }, "typed-array-buffer": { "id": 262, - "package_id": 395, + "package_id": 397, }, "typed-array-byte-length": { "id": 263, - "package_id": 396, + "package_id": 398, }, "typed-array-byte-offset": { "id": 264, - "package_id": 397, + "package_id": 399, }, "typed-array-length": { "id": 265, - "package_id": 398, + "package_id": 400, }, "typescript": { "id": 13, - "package_id": 399, + "package_id": 401, }, "unbox-primitive": { "id": 266, - "package_id": 400, + "package_id": 402, }, "unbzip2-stream": { "id": 57, - "package_id": 401, + "package_id": 403, }, "undici-types": { - "id": 866, - "package_id": 402, + "id": 870, + "package_id": 404, }, "universalify": { "id": 441, - "package_id": 403, + "package_id": 405, }, "update-browserslist-db": { "id": 160, - "package_id": 404, + "package_id": 406, }, "uri-js": { "id": 89, - "package_id": 405, + "package_id": 407, }, "urlpattern-polyfill": { "id": 183, - "package_id": 406, + "package_id": 408, }, "util-deprecate": { "id": 624, - "package_id": 407, + "package_id": 409, }, "which": { "id": 196, - "package_id": 408, + "package_id": 410, }, "which-boxed-primitive": { "id": 803, - "package_id": 409, + "package_id": 411, }, "which-builtin-type": { "id": 659, - "package_id": 410, + "package_id": 412, }, "which-collection": { "id": 826, - "package_id": 411, + "package_id": 413, }, "which-typed-array": { "id": 267, - "package_id": 412, + "package_id": 414, }, "word-wrap": { "id": 588, - "package_id": 413, + "package_id": 415, }, "wrap-ansi": { "id": 187, - "package_id": 414, + "package_id": 416, }, "wrap-ansi-cjs": { "id": 40, - "package_id": 414, + "package_id": 417, }, "wrappy": { "id": 582, - "package_id": 415, + "package_id": 418, }, "ws": { "id": 646, - "package_id": 416, + "package_id": 419, }, "y18n": { "id": 850, - "package_id": 417, + "package_id": 420, }, "yallist": { "id": 893, - "package_id": 418, + "package_id": 421, }, "yaml": { "id": 620, - "package_id": 419, + "package_id": 422, }, "yargs": { "id": 58, - "package_id": 420, + "package_id": 423, }, "yargs-parser": { "id": 851, - "package_id": 421, + "package_id": 424, }, "yauzl": { "id": 421, - "package_id": 422, + "package_id": 425, }, "yocto-queue": { "id": 589, - "package_id": 423, + "package_id": 426, }, "zod": { "id": 184, - "package_id": 424, + "package_id": 427, }, }, "depth": 0, @@ -22446,7 +22698,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "@types/node": { "id": 163, - "package_id": 431, + "package_id": 438, }, }, "depth": 1, @@ -22457,7 +22709,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "postcss": { "id": 560, - "package_id": 438, + "package_id": 448, }, }, "depth": 1, @@ -22468,7 +22720,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "@types/node": { "id": 64, - "package_id": 431, + "package_id": 434, }, }, "depth": 1, @@ -22479,7 +22731,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "debug": { "id": 343, - "package_id": 434, + "package_id": 440, }, }, "depth": 1, @@ -22490,11 +22742,11 @@ exports[`next build works: bun 1`] = ` "dependencies": { "debug": { "id": 361, - "package_id": 434, + "package_id": 442, }, "doctrine": { "id": 362, - "package_id": 435, + "package_id": 443, }, }, "depth": 1, @@ -22505,11 +22757,11 @@ exports[`next build works: bun 1`] = ` "dependencies": { "doctrine": { "id": 397, - "package_id": 435, + "package_id": 444, }, "resolve": { "id": 407, - "package_id": 436, + "package_id": 445, }, }, "depth": 1, @@ -22520,11 +22772,11 @@ exports[`next build works: bun 1`] = ` "dependencies": { "debug": { "id": 51, - "package_id": 429, + "package_id": 432, }, "semver": { "id": 55, - "package_id": 430, + "package_id": 433, }, }, "depth": 1, @@ -22535,7 +22787,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "glob-parent": { "id": 176, - "package_id": 433, + "package_id": 439, }, }, "depth": 1, @@ -22546,7 +22798,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "glob-parent": { "id": 424, - "package_id": 433, + "package_id": 446, }, }, "depth": 1, @@ -22557,7 +22809,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "lilconfig": { "id": 619, - "package_id": 440, + "package_id": 450, }, }, "depth": 1, @@ -22568,7 +22820,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "minimatch": { "id": 462, - "package_id": 437, + "package_id": 447, }, }, "depth": 1, @@ -22579,11 +22831,11 @@ exports[`next build works: bun 1`] = ` "dependencies": { "minimatch": { "id": 79, - "package_id": 432, + "package_id": 436, }, "semver": { "id": 80, - "package_id": 430, + "package_id": 437, }, }, "depth": 1, @@ -22594,7 +22846,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "debug": { "id": 355, - "package_id": 434, + "package_id": 441, }, }, "depth": 1, @@ -22605,7 +22857,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "lru-cache": { "id": 865, - "package_id": 448, + "package_id": 459, }, }, "depth": 2, @@ -22616,7 +22868,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "glob": { "id": 667, - "package_id": 441, + "package_id": 451, }, }, "depth": 1, @@ -22627,7 +22879,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "brace-expansion": { "id": 881, - "package_id": 449, + "package_id": 462, }, }, "depth": 2, @@ -22638,7 +22890,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "lru-cache": { "id": 606, - "package_id": 439, + "package_id": 449, }, }, "depth": 1, @@ -22649,7 +22901,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "brace-expansion": { "id": 868, - "package_id": 449, + "package_id": 460, }, }, "depth": 2, @@ -22659,8 +22911,8 @@ exports[`next build works: bun 1`] = ` { "dependencies": { "lru-cache": { - "id": 865, - "package_id": 448, + "id": 869, + "package_id": 461, }, }, "depth": 2, @@ -22671,7 +22923,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "@types/node": { "id": 65, - "package_id": 431, + "package_id": 435, }, }, "depth": 1, @@ -22682,7 +22934,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "emoji-regex": { "id": 701, - "package_id": 442, + "package_id": 452, }, }, "depth": 1, @@ -22693,15 +22945,15 @@ exports[`next build works: bun 1`] = ` "dependencies": { "string-width": { "id": 35, - "package_id": 426, + "package_id": 429, }, "strip-ansi": { "id": 37, - "package_id": 427, + "package_id": 430, }, "wrap-ansi": { "id": 39, - "package_id": 428, + "package_id": 431, }, }, "depth": 1, @@ -22712,7 +22964,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "chalk": { "id": 17, - "package_id": 425, + "package_id": 428, }, }, "depth": 1, @@ -22722,8 +22974,8 @@ exports[`next build works: bun 1`] = ` { "dependencies": { "emoji-regex": { - "id": 701, - "package_id": 442, + "id": 704, + "package_id": 453, }, }, "depth": 1, @@ -22734,7 +22986,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "ansi-regex": { "id": 860, - "package_id": 446, + "package_id": 457, }, }, "depth": 2, @@ -22745,7 +22997,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "ansi-styles": { "id": 861, - "package_id": 447, + "package_id": 458, }, }, "depth": 2, @@ -22756,15 +23008,15 @@ exports[`next build works: bun 1`] = ` "dependencies": { "ansi-styles": { "id": 854, - "package_id": 443, + "package_id": 454, }, "escape-string-regexp": { "id": 855, - "package_id": 444, + "package_id": 455, }, "supports-color": { "id": 856, - "package_id": 445, + "package_id": 456, }, }, "depth": 2, @@ -22775,7 +23027,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "color-convert": { "id": 891, - "package_id": 450, + "package_id": 463, }, }, "depth": 3, @@ -22786,7 +23038,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "has-flag": { "id": 892, - "package_id": 451, + "package_id": 464, }, }, "depth": 3, @@ -22797,7 +23049,7 @@ exports[`next build works: bun 1`] = ` "dependencies": { "color-name": { "id": 897, - "package_id": 452, + "package_id": 465, }, }, "depth": 4, @@ -22980,7 +23232,7 @@ exports[`next build works: node 1`] = ` "name": "tailwindcss", "version": "==3.3.3", }, - "package_id": 379, + "package_id": 381, }, { "behavior": { @@ -22993,7 +23245,7 @@ exports[`next build works: node 1`] = ` "name": "typescript", "version": "==5.2.2", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -23045,7 +23297,7 @@ exports[`next build works: node 1`] = ` "name": "chalk", "version": ">=2.4.2 <3.0.0", }, - "package_id": 425, + "package_id": 428, }, { "behavior": { @@ -23227,7 +23479,7 @@ exports[`next build works: node 1`] = ` "name": "strip-json-comments", "version": ">=3.1.1 <4.0.0", }, - "package_id": 374, + "package_id": 376, }, { "behavior": { @@ -23279,7 +23531,7 @@ exports[`next build works: node 1`] = ` "name": "string-width", "version": ">=5.1.2 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -23293,7 +23545,7 @@ exports[`next build works: node 1`] = ` "name": "string-width", "version": ">=4.2.0 <5.0.0", }, - "package_id": 367, + "package_id": 368, }, { "behavior": { @@ -23306,7 +23558,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -23320,7 +23572,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 374, }, { "behavior": { @@ -23333,7 +23585,7 @@ exports[`next build works: node 1`] = ` "name": "wrap-ansi", "version": ">=8.1.0 <9.0.0", }, - "package_id": 428, + "package_id": 431, }, { "behavior": { @@ -23347,7 +23599,7 @@ exports[`next build works: node 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 417, }, { "behavior": { @@ -23490,7 +23742,7 @@ exports[`next build works: node 1`] = ` "name": "debug", "version": "==4.3.4", }, - "package_id": 429, + "package_id": 432, }, { "behavior": { @@ -23542,7 +23794,7 @@ exports[`next build works: node 1`] = ` "name": "semver", "version": "==7.6.0", }, - "package_id": 430, + "package_id": 433, }, { "behavior": { @@ -23555,7 +23807,7 @@ exports[`next build works: node 1`] = ` "name": "tar-fs", "version": "==3.0.5", }, - "package_id": 381, + "package_id": 383, }, { "behavior": { @@ -23568,7 +23820,7 @@ exports[`next build works: node 1`] = ` "name": "unbzip2-stream", "version": "==1.4.3", }, - "package_id": 401, + "package_id": 403, }, { "behavior": { @@ -23581,7 +23833,7 @@ exports[`next build works: node 1`] = ` "name": "yargs", "version": "==17.7.2", }, - "package_id": 420, + "package_id": 423, }, { "behavior": { @@ -23594,7 +23846,7 @@ exports[`next build works: node 1`] = ` "name": "tslib", "version": ">=2.4.0 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -23659,7 +23911,7 @@ exports[`next build works: node 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 434, }, { "behavior": { @@ -23672,7 +23924,7 @@ exports[`next build works: node 1`] = ` "name": "@types/node", "version": ">=0.0.0", }, - "package_id": 431, + "package_id": 435, }, { "behavior": { @@ -23854,7 +24106,7 @@ exports[`next build works: node 1`] = ` "name": "minimatch", "version": "==9.0.3", }, - "package_id": 432, + "package_id": 436, }, { "behavior": { @@ -23867,7 +24119,7 @@ exports[`next build works: node 1`] = ` "name": "semver", "version": ">=7.5.4 <8.0.0", }, - "package_id": 430, + "package_id": 437, }, { "behavior": { @@ -23880,7 +24132,7 @@ exports[`next build works: node 1`] = ` "name": "ts-api-utils", "version": ">=1.0.1 <2.0.0", }, - "package_id": 389, + "package_id": 391, }, { "behavior": { @@ -23984,7 +24236,7 @@ exports[`next build works: node 1`] = ` "name": "uri-js", "version": ">=4.2.2 <5.0.0", }, - "package_id": 405, + "package_id": 407, }, { "behavior": { @@ -24634,7 +24886,7 @@ exports[`next build works: node 1`] = ` "name": "tslib", "version": ">=2.0.1 <3.0.0", }, - "package_id": 392, + "package_id": 394, }, { "behavior": { @@ -24907,7 +25159,7 @@ exports[`next build works: node 1`] = ` "name": "update-browserslist-db", "version": ">=1.0.13 <2.0.0", }, - "package_id": 404, + "package_id": 406, }, { "behavior": { @@ -24946,7 +25198,7 @@ exports[`next build works: node 1`] = ` "name": "@types/node", "version": ">=20.12.8 <20.13.0", }, - "package_id": 431, + "package_id": 438, }, { "behavior": { @@ -25063,7 +25315,7 @@ exports[`next build works: node 1`] = ` "name": "supports-color", "version": ">=7.1.0 <8.0.0", }, - "package_id": 377, + "package_id": 379, }, { "behavior": { @@ -25115,7 +25367,7 @@ exports[`next build works: node 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <5.2.0", }, - "package_id": 433, + "package_id": 439, }, { "behavior": { @@ -25206,7 +25458,7 @@ exports[`next build works: node 1`] = ` "name": "urlpattern-polyfill", "version": "==10.0.0", }, - "package_id": 406, + "package_id": 408, }, { "behavior": { @@ -25219,7 +25471,7 @@ exports[`next build works: node 1`] = ` "name": "zod", "version": "==3.23.8", }, - "package_id": 424, + "package_id": 427, }, { "behavior": { @@ -25245,7 +25497,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -25258,7 +25510,7 @@ exports[`next build works: node 1`] = ` "name": "wrap-ansi", "version": ">=7.0.0 <8.0.0", }, - "package_id": 414, + "package_id": 416, }, { "behavior": { @@ -25285,7 +25537,7 @@ exports[`next build works: node 1`] = ` "name": "typescript", "version": ">=4.9.5", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -25376,7 +25628,7 @@ exports[`next build works: node 1`] = ` "name": "which", "version": ">=2.0.1 <3.0.0", }, - "package_id": 408, + "package_id": 410, }, { "behavior": { @@ -25688,7 +25940,7 @@ exports[`next build works: node 1`] = ` "name": "tapable", "version": ">=2.2.0 <3.0.0", }, - "package_id": 380, + "package_id": 382, }, { "behavior": { @@ -26195,7 +26447,7 @@ exports[`next build works: node 1`] = ` "name": "string.prototype.trim", "version": ">=1.2.9 <2.0.0", }, - "package_id": 369, + "package_id": 370, }, { "behavior": { @@ -26208,7 +26460,7 @@ exports[`next build works: node 1`] = ` "name": "string.prototype.trimend", "version": ">=1.0.8 <2.0.0", }, - "package_id": 370, + "package_id": 371, }, { "behavior": { @@ -26221,7 +26473,7 @@ exports[`next build works: node 1`] = ` "name": "string.prototype.trimstart", "version": ">=1.0.8 <2.0.0", }, - "package_id": 371, + "package_id": 372, }, { "behavior": { @@ -26234,7 +26486,7 @@ exports[`next build works: node 1`] = ` "name": "typed-array-buffer", "version": ">=1.0.2 <2.0.0", }, - "package_id": 395, + "package_id": 397, }, { "behavior": { @@ -26247,7 +26499,7 @@ exports[`next build works: node 1`] = ` "name": "typed-array-byte-length", "version": ">=1.0.1 <2.0.0", }, - "package_id": 396, + "package_id": 398, }, { "behavior": { @@ -26260,7 +26512,7 @@ exports[`next build works: node 1`] = ` "name": "typed-array-byte-offset", "version": ">=1.0.2 <2.0.0", }, - "package_id": 397, + "package_id": 399, }, { "behavior": { @@ -26273,7 +26525,7 @@ exports[`next build works: node 1`] = ` "name": "typed-array-length", "version": ">=1.0.6 <2.0.0", }, - "package_id": 398, + "package_id": 400, }, { "behavior": { @@ -26286,7 +26538,7 @@ exports[`next build works: node 1`] = ` "name": "unbox-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 400, + "package_id": 402, }, { "behavior": { @@ -26299,7 +26551,7 @@ exports[`next build works: node 1`] = ` "name": "which-typed-array", "version": ">=1.1.15 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -27118,7 +27370,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -27131,7 +27383,7 @@ exports[`next build works: node 1`] = ` "name": "text-table", "version": ">=0.2.0 <0.3.0", }, - "package_id": 384, + "package_id": 386, }, { "behavior": { @@ -27158,7 +27410,7 @@ exports[`next build works: node 1`] = ` "name": "typescript", "version": ">=3.3.1", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -27288,7 +27540,7 @@ exports[`next build works: node 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 440, }, { "behavior": { @@ -27444,7 +27696,7 @@ exports[`next build works: node 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 441, }, { "behavior": { @@ -27522,7 +27774,7 @@ exports[`next build works: node 1`] = ` "name": "debug", "version": ">=3.2.7 <4.0.0", }, - "package_id": 434, + "package_id": 442, }, { "behavior": { @@ -27535,7 +27787,7 @@ exports[`next build works: node 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 443, }, { "behavior": { @@ -27678,7 +27930,7 @@ exports[`next build works: node 1`] = ` "name": "tsconfig-paths", "version": ">=3.15.0 <4.0.0", }, - "package_id": 391, + "package_id": 393, }, { "behavior": { @@ -27990,7 +28242,7 @@ exports[`next build works: node 1`] = ` "name": "doctrine", "version": ">=2.1.0 <3.0.0", }, - "package_id": 435, + "package_id": 444, }, { "behavior": { @@ -28120,7 +28372,7 @@ exports[`next build works: node 1`] = ` "name": "resolve", "version": ">=2.0.0-next.5 <3.0.0", }, - "package_id": 436, + "package_id": 445, }, { "behavior": { @@ -28146,7 +28398,7 @@ exports[`next build works: node 1`] = ` "name": "string.prototype.matchall", "version": ">=4.0.11 <5.0.0", }, - "package_id": 368, + "package_id": 369, }, { "behavior": { @@ -28302,7 +28554,7 @@ exports[`next build works: node 1`] = ` "name": "yauzl", "version": ">=2.10.0 <3.0.0", }, - "package_id": 422, + "package_id": 425, }, { "behavior": { @@ -28341,7 +28593,7 @@ exports[`next build works: node 1`] = ` "name": "glob-parent", "version": ">=5.1.2 <6.0.0", }, - "package_id": 433, + "package_id": 446, }, { "behavior": { @@ -28419,7 +28671,7 @@ exports[`next build works: node 1`] = ` "name": "to-regex-range", "version": ">=5.0.1 <6.0.0", }, - "package_id": 388, + "package_id": 390, }, { "behavior": { @@ -28562,7 +28814,7 @@ exports[`next build works: node 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -28835,7 +29087,7 @@ exports[`next build works: node 1`] = ` "name": "minimatch", "version": ">=9.0.1 <10.0.0", }, - "package_id": 437, + "package_id": 447, }, { "behavior": { @@ -28887,7 +29139,7 @@ exports[`next build works: node 1`] = ` "name": "type-fest", "version": ">=0.20.2 <0.21.0", }, - "package_id": 394, + "package_id": 396, }, { "behavior": { @@ -29147,7 +29399,7 @@ exports[`next build works: node 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -29472,7 +29724,7 @@ exports[`next build works: node 1`] = ` "name": "which-typed-array", "version": ">=1.1.14 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -29654,7 +29906,7 @@ exports[`next build works: node 1`] = ` "name": "universalify", "version": ">=2.0.0 <3.0.0", }, - "package_id": 403, + "package_id": 405, }, { "behavior": { @@ -29758,7 +30010,7 @@ exports[`next build works: node 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -29862,7 +30114,7 @@ exports[`next build works: node 1`] = ` "name": "thenify-all", "version": ">=1.0.0 <2.0.0", }, - "package_id": 386, + "package_id": 388, }, { "behavior": { @@ -30111,7 +30363,7 @@ exports[`next build works: node 1`] = ` "name": "postcss", "version": "==8.4.31", }, - "package_id": 438, + "package_id": 448, }, { "behavior": { @@ -30124,7 +30376,7 @@ exports[`next build works: node 1`] = ` "name": "styled-jsx", "version": "==5.1.1", }, - "package_id": 375, + "package_id": 377, }, { "behavior": { @@ -30397,7 +30649,7 @@ exports[`next build works: node 1`] = ` "name": "wrappy", "version": "<2.0.0 >=1.0.0", }, - "package_id": 415, + "package_id": 418, }, { "behavior": { @@ -30462,7 +30714,7 @@ exports[`next build works: node 1`] = ` "name": "type-check", "version": ">=0.4.0 <0.5.0", }, - "package_id": 393, + "package_id": 395, }, { "behavior": { @@ -30475,7 +30727,7 @@ exports[`next build works: node 1`] = ` "name": "word-wrap", "version": ">=1.2.5 <2.0.0", }, - "package_id": 413, + "package_id": 415, }, { "behavior": { @@ -30488,7 +30740,7 @@ exports[`next build works: node 1`] = ` "name": "yocto-queue", "version": ">=0.1.0 <0.2.0", }, - "package_id": 423, + "package_id": 426, }, { "behavior": { @@ -30709,7 +30961,7 @@ exports[`next build works: node 1`] = ` "name": "lru-cache", "version": ">=10.2.0 <11.0.0", }, - "package_id": 439, + "package_id": 449, }, { "behavior": { @@ -30880,7 +31132,7 @@ exports[`next build works: node 1`] = ` "name": "lilconfig", "version": ">=3.0.0 <4.0.0", }, - "package_id": 440, + "package_id": 450, }, { "behavior": { @@ -30893,7 +31145,7 @@ exports[`next build works: node 1`] = ` "name": "yaml", "version": ">=2.3.4 <3.0.0", }, - "package_id": 419, + "package_id": 422, }, { "behavior": { @@ -30945,7 +31197,7 @@ exports[`next build works: node 1`] = ` "name": "util-deprecate", "version": ">=1.0.2 <2.0.0", }, - "package_id": 407, + "package_id": 409, }, { "behavior": { @@ -31231,7 +31483,7 @@ exports[`next build works: node 1`] = ` "name": "ws", "version": "==8.17.1", }, - "package_id": 416, + "package_id": 419, }, { "behavior": { @@ -31400,7 +31652,7 @@ exports[`next build works: node 1`] = ` "name": "which-builtin-type", "version": ">=1.1.3 <2.0.0", }, - "package_id": 410, + "package_id": 412, }, { "behavior": { @@ -31491,7 +31743,7 @@ exports[`next build works: node 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -31504,7 +31756,7 @@ exports[`next build works: node 1`] = ` "name": "glob", "version": ">=7.1.3 <8.0.0", }, - "package_id": 441, + "package_id": 451, }, { "behavior": { @@ -31933,7 +32185,7 @@ exports[`next build works: node 1`] = ` "name": "text-decoder", "version": ">=1.1.0 <2.0.0", }, - "package_id": 383, + "package_id": 385, }, { "behavior": { @@ -31946,7 +32198,7 @@ exports[`next build works: node 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": 442, + "package_id": 452, }, { "behavior": { @@ -31972,7 +32224,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -31985,7 +32237,7 @@ exports[`next build works: node 1`] = ` "name": "emoji-regex", "version": ">=8.0.0 <9.0.0", }, - "package_id": null, + "package_id": 453, }, { "behavior": { @@ -31998,7 +32250,7 @@ exports[`next build works: node 1`] = ` "name": "is-fullwidth-code-point", "version": ">=3.0.0 <4.0.0", }, - "package_id": null, + "package_id": 228, }, { "behavior": { @@ -32011,7 +32263,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.1 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -32323,7 +32575,7 @@ exports[`next build works: node 1`] = ` "name": "ansi-regex", "version": ">=5.0.1 <6.0.0", }, - "package_id": null, + "package_id": 55, }, { "behavior": { @@ -32440,7 +32692,7 @@ exports[`next build works: node 1`] = ` "name": "ts-interface-checker", "version": ">=0.1.9 <0.2.0", }, - "package_id": 390, + "package_id": 392, }, { "behavior": { @@ -32739,7 +32991,7 @@ exports[`next build works: node 1`] = ` "name": "sucrase", "version": ">=3.32.0 <4.0.0", }, - "package_id": 376, + "package_id": 378, }, { "behavior": { @@ -32791,7 +33043,7 @@ exports[`next build works: node 1`] = ` "name": "tar-stream", "version": ">=3.1.5 <4.0.0", }, - "package_id": 382, + "package_id": 384, }, { "behavior": { @@ -32869,7 +33121,7 @@ exports[`next build works: node 1`] = ` "name": "thenify", "version": ">=3.1.0 && <4.0.0", }, - "package_id": 385, + "package_id": 387, }, { "behavior": { @@ -32895,7 +33147,7 @@ exports[`next build works: node 1`] = ` "name": "typescript", "version": ">=4.2.0", }, - "package_id": 399, + "package_id": 401, }, { "behavior": { @@ -32947,7 +33199,7 @@ exports[`next build works: node 1`] = ` "name": "strip-bom", "version": ">=3.0.0 <4.0.0", }, - "package_id": 373, + "package_id": 375, }, { "behavior": { @@ -33272,7 +33524,7 @@ exports[`next build works: node 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -33298,7 +33550,7 @@ exports[`next build works: node 1`] = ` "name": "through", "version": ">=2.3.8 <3.0.0", }, - "package_id": 387, + "package_id": 389, }, { "behavior": { @@ -33558,7 +33810,7 @@ exports[`next build works: node 1`] = ` "name": "which-boxed-primitive", "version": ">=1.0.2 <2.0.0", }, - "package_id": 409, + "package_id": 411, }, { "behavior": { @@ -33571,7 +33823,7 @@ exports[`next build works: node 1`] = ` "name": "which-collection", "version": ">=1.0.1 <2.0.0", }, - "package_id": 411, + "package_id": 413, }, { "behavior": { @@ -33584,7 +33836,7 @@ exports[`next build works: node 1`] = ` "name": "which-typed-array", "version": ">=1.1.9 <2.0.0", }, - "package_id": 412, + "package_id": 414, }, { "behavior": { @@ -33740,7 +33992,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": 372, + "package_id": 373, }, { "behavior": { @@ -33753,7 +34005,7 @@ exports[`next build works: node 1`] = ` "name": "ansi-styles", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 56, }, { "behavior": { @@ -33766,7 +34018,7 @@ exports[`next build works: node 1`] = ` "name": "string-width", "version": ">=4.1.0 <5.0.0", }, - "package_id": null, + "package_id": 367, }, { "behavior": { @@ -33779,7 +34031,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 373, }, { "behavior": { @@ -33885,7 +34137,7 @@ exports[`next build works: node 1`] = ` "name": "y18n", "version": ">=5.0.5 <6.0.0", }, - "package_id": 417, + "package_id": 420, }, { "behavior": { @@ -33898,7 +34150,7 @@ exports[`next build works: node 1`] = ` "name": "yargs-parser", "version": ">=21.1.1 <22.0.0", }, - "package_id": 421, + "package_id": 424, }, { "behavior": { @@ -33937,7 +34189,7 @@ exports[`next build works: node 1`] = ` "name": "ansi-styles", "version": ">=3.2.1 <4.0.0", }, - "package_id": 443, + "package_id": 454, }, { "behavior": { @@ -33950,7 +34202,7 @@ exports[`next build works: node 1`] = ` "name": "escape-string-regexp", "version": ">=1.0.5 <2.0.0", }, - "package_id": 444, + "package_id": 455, }, { "behavior": { @@ -33963,7 +34215,7 @@ exports[`next build works: node 1`] = ` "name": "supports-color", "version": ">=5.3.0 <6.0.0", }, - "package_id": 445, + "package_id": 456, }, { "behavior": { @@ -34002,7 +34254,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -34015,7 +34267,7 @@ exports[`next build works: node 1`] = ` "name": "ansi-regex", "version": ">=6.0.1 <7.0.0", }, - "package_id": 446, + "package_id": 457, }, { "behavior": { @@ -34028,7 +34280,7 @@ exports[`next build works: node 1`] = ` "name": "ansi-styles", "version": ">=6.1.0 <7.0.0", }, - "package_id": 447, + "package_id": 458, }, { "behavior": { @@ -34041,7 +34293,7 @@ exports[`next build works: node 1`] = ` "name": "string-width", "version": ">=5.0.1 <6.0.0", }, - "package_id": 426, + "package_id": 429, }, { "behavior": { @@ -34054,7 +34306,7 @@ exports[`next build works: node 1`] = ` "name": "strip-ansi", "version": ">=7.0.1 <8.0.0", }, - "package_id": 427, + "package_id": 430, }, { "behavior": { @@ -34080,7 +34332,7 @@ exports[`next build works: node 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": 448, + "package_id": 459, }, { "behavior": { @@ -34093,7 +34345,7 @@ exports[`next build works: node 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": 402, + "package_id": 404, }, { "behavior": { @@ -34106,7 +34358,7 @@ exports[`next build works: node 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -34119,7 +34371,7 @@ exports[`next build works: node 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 460, }, { "behavior": { @@ -34132,7 +34384,7 @@ exports[`next build works: node 1`] = ` "name": "lru-cache", "version": ">=6.0.0 <7.0.0", }, - "package_id": null, + "package_id": 461, }, { "behavior": { @@ -34145,7 +34397,7 @@ exports[`next build works: node 1`] = ` "name": "undici-types", "version": ">=5.26.4 <5.27.0", }, - "package_id": null, + "package_id": 404, }, { "behavior": { @@ -34184,7 +34436,7 @@ exports[`next build works: node 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -34197,7 +34449,7 @@ exports[`next build works: node 1`] = ` "name": "ms", "version": ">=2.1.1 <3.0.0", }, - "package_id": null, + "package_id": 276, }, { "behavior": { @@ -34223,7 +34475,7 @@ exports[`next build works: node 1`] = ` "name": "esutils", "version": ">=2.0.2 <3.0.0", }, - "package_id": null, + "package_id": 162, }, { "behavior": { @@ -34262,7 +34514,7 @@ exports[`next build works: node 1`] = ` "name": "supports-preserve-symlinks-flag", "version": ">=1.0.0 <2.0.0", }, - "package_id": 378, + "package_id": 380, }, { "behavior": { @@ -34275,7 +34527,7 @@ exports[`next build works: node 1`] = ` "name": "is-glob", "version": ">=4.0.1 <5.0.0", }, - "package_id": null, + "package_id": 230, }, { "behavior": { @@ -34288,7 +34540,7 @@ exports[`next build works: node 1`] = ` "name": "brace-expansion", "version": ">=2.0.1 <3.0.0", }, - "package_id": 449, + "package_id": 462, }, { "behavior": { @@ -34418,7 +34670,7 @@ exports[`next build works: node 1`] = ` "name": "color-convert", "version": ">=1.9.0 <2.0.0", }, - "package_id": 450, + "package_id": 463, }, { "behavior": { @@ -34431,7 +34683,7 @@ exports[`next build works: node 1`] = ` "name": "has-flag", "version": ">=3.0.0 <4.0.0", }, - "package_id": 451, + "package_id": 464, }, { "behavior": { @@ -34444,7 +34696,7 @@ exports[`next build works: node 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": 418, + "package_id": 421, }, { "behavior": { @@ -34470,7 +34722,7 @@ exports[`next build works: node 1`] = ` "name": "yallist", "version": ">=4.0.0 <5.0.0", }, - "package_id": null, + "package_id": 421, }, { "behavior": { @@ -34483,7 +34735,7 @@ exports[`next build works: node 1`] = ` "name": "balanced-match", "version": ">=1.0.0 <2.0.0", }, - "package_id": null, + "package_id": 79, }, { "behavior": { @@ -34496,7 +34748,7 @@ exports[`next build works: node 1`] = ` "name": "color-name", "version": "==1.1.3", }, - "package_id": 452, + "package_id": 465, }, ], "format": "v2", @@ -34541,7 +34793,9 @@ exports[`next build works: node 1`] = ` "@tootallnate/quickjs-emscripten": 37, "@types/json5": 38, "@types/node": [ - 431, + 434, + 435, + 438, 39, ], "@types/prop-types": 40, @@ -34560,13 +34814,13 @@ exports[`next build works: node 1`] = ` "agent-base": 53, "ajv": 54, "ansi-regex": [ - 446, + 457, 55, ], "ansi-styles": [ - 447, + 458, 56, - 443, + 454, ], "any-promise": 57, "anymatch": 58, @@ -34600,7 +34854,8 @@ exports[`next build works: node 1`] = ` "basic-ftp": 86, "binary-extensions": 87, "brace-expansion": [ - 449, + 460, + 462, 88, ], "braces": 89, @@ -34615,7 +34870,7 @@ exports[`next build works: node 1`] = ` "caniuse-lite": 98, "chalk": [ 99, - 425, + 428, ], "chokidar": 100, "chromium-bidi": 101, @@ -34623,11 +34878,11 @@ exports[`next build works: node 1`] = ` "cliui": 103, "color-convert": [ 104, - 450, + 463, ], "color-name": [ 105, - 452, + 465, ], "commander": 106, "concat-map": 107, @@ -34642,8 +34897,10 @@ exports[`next build works: node 1`] = ` "data-view-byte-offset": 116, "debug": [ 117, - 429, - 434, + 432, + 440, + 441, + 442, ], "deep-is": 118, "default-create-template": 0, @@ -34657,13 +34914,15 @@ exports[`next build works: node 1`] = ` "dlv": 126, "doctrine": [ 127, - 435, + 443, + 444, ], "eastasianwidth": 128, "electron-to-chromium": 129, "emoji-regex": [ 130, - 442, + 452, + 453, ], "end-of-stream": 131, "enhanced-resolve": 132, @@ -34680,7 +34939,7 @@ exports[`next build works: node 1`] = ` "escalade": 143, "escape-string-regexp": [ 144, - 444, + 455, ], "escodegen": 145, "eslint": 146, @@ -34730,11 +34989,12 @@ exports[`next build works: node 1`] = ` "get-uri": 190, "glob": [ 191, - 441, + 451, ], "glob-parent": [ 192, - 433, + 439, + 446, ], "globals": 193, "globalthis": 194, @@ -34745,7 +35005,7 @@ exports[`next build works: node 1`] = ` "has-bigints": 199, "has-flag": [ 200, - 451, + 464, ], "has-property-descriptors": 201, "has-proto": 202, @@ -34811,7 +35071,7 @@ exports[`next build works: node 1`] = ` "language-tags": 262, "levn": 263, "lilconfig": [ - 440, + 450, 264, ], "lines-and-columns": 265, @@ -34819,15 +35079,16 @@ exports[`next build works: node 1`] = ` "lodash.merge": 267, "loose-envify": 268, "lru-cache": [ - 439, + 449, 269, - 448, + 459, + 461, ], "merge2": 270, "micromatch": 271, "minimatch": [ - 437, - 432, + 447, + 436, 272, ], "minimist": 273, @@ -34873,7 +35134,7 @@ exports[`next build works: node 1`] = ` "pirates": 313, "possible-typed-array-names": 314, "postcss": [ - 438, + 448, 315, ], "postcss-import": 316, @@ -34903,7 +35164,7 @@ exports[`next build works: node 1`] = ` "regexp.prototype.flags": 340, "require-directory": 341, "resolve": [ - 436, + 445, 342, ], "resolve-from": 343, @@ -34915,7 +35176,8 @@ exports[`next build works: node 1`] = ` "safe-regex-test": 349, "scheduler": 350, "semver": [ - 430, + 433, + 437, 351, ], "set-function-length": 352, @@ -34934,75 +35196,78 @@ exports[`next build works: node 1`] = ` "streamsearch": 365, "streamx": 366, "string-width": [ - 426, + 429, 367, + 368, ], - "string.prototype.matchall": 368, - "string.prototype.trim": 369, - "string.prototype.trimend": 370, - "string.prototype.trimstart": 371, + "string.prototype.matchall": 369, + "string.prototype.trim": 370, + "string.prototype.trimend": 371, + "string.prototype.trimstart": 372, "strip-ansi": [ - 427, - 372, + 430, + 373, + 374, ], - "strip-bom": 373, - "strip-json-comments": 374, - "styled-jsx": 375, - "sucrase": 376, + "strip-bom": 375, + "strip-json-comments": 376, + "styled-jsx": 377, + "sucrase": 378, "supports-color": [ - 377, - 445, + 379, + 456, ], - "supports-preserve-symlinks-flag": 378, - "tailwindcss": 379, - "tapable": 380, - "tar-fs": 381, - "tar-stream": 382, - "text-decoder": 383, - "text-table": 384, - "thenify": 385, - "thenify-all": 386, - "through": 387, - "to-regex-range": 388, - "ts-api-utils": 389, - "ts-interface-checker": 390, - "tsconfig-paths": 391, - "tslib": 392, - "type-check": 393, - "type-fest": 394, - "typed-array-buffer": 395, - "typed-array-byte-length": 396, - "typed-array-byte-offset": 397, - "typed-array-length": 398, - "typescript": 399, - "unbox-primitive": 400, - "unbzip2-stream": 401, - "undici-types": 402, - "universalify": 403, - "update-browserslist-db": 404, - "uri-js": 405, - "urlpattern-polyfill": 406, - "util-deprecate": 407, - "which": 408, - "which-boxed-primitive": 409, - "which-builtin-type": 410, - "which-collection": 411, - "which-typed-array": 412, - "word-wrap": 413, + "supports-preserve-symlinks-flag": 380, + "tailwindcss": 381, + "tapable": 382, + "tar-fs": 383, + "tar-stream": 384, + "text-decoder": 385, + "text-table": 386, + "thenify": 387, + "thenify-all": 388, + "through": 389, + "to-regex-range": 390, + "ts-api-utils": 391, + "ts-interface-checker": 392, + "tsconfig-paths": 393, + "tslib": 394, + "type-check": 395, + "type-fest": 396, + "typed-array-buffer": 397, + "typed-array-byte-length": 398, + "typed-array-byte-offset": 399, + "typed-array-length": 400, + "typescript": 401, + "unbox-primitive": 402, + "unbzip2-stream": 403, + "undici-types": 404, + "universalify": 405, + "update-browserslist-db": 406, + "uri-js": 407, + "urlpattern-polyfill": 408, + "util-deprecate": 409, + "which": 410, + "which-boxed-primitive": 411, + "which-builtin-type": 412, + "which-collection": 413, + "which-typed-array": 414, + "word-wrap": 415, "wrap-ansi": [ - 428, - 414, + 431, + 416, + 417, ], - "wrappy": 415, - "ws": 416, - "y18n": 417, - "yallist": 418, - "yaml": 419, - "yargs": 420, - "yargs-parser": 421, - "yauzl": 422, - "yocto-queue": 423, - "zod": 424, + "wrappy": 418, + "ws": 419, + "y18n": 420, + "yallist": 421, + "yaml": 422, + "yargs": 423, + "yargs-parser": 424, + "yauzl": 425, + "yocto-queue": 426, + "zod": 427, }, "packages": [ { @@ -41918,6 +42183,26 @@ exports[`next build works: node 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 704, + 705, + 706, + ], + "id": 368, + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "man_dir": "", + "name": "string-width", + "name_hash": "15727733666069179645", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "tag": "npm", + "value": "4.2.3", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ @@ -41934,7 +42219,7 @@ exports[`next build works: node 1`] = ` 717, 718, ], - "id": 368, + "id": 369, "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "man_dir": "", "name": "string.prototype.matchall", @@ -41955,7 +42240,7 @@ exports[`next build works: node 1`] = ` 721, 722, ], - "id": 369, + "id": 370, "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "man_dir": "", "name": "string.prototype.trim", @@ -41975,7 +42260,7 @@ exports[`next build works: node 1`] = ` 724, 725, ], - "id": 370, + "id": 371, "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "man_dir": "", "name": "string.prototype.trimend", @@ -41995,7 +42280,7 @@ exports[`next build works: node 1`] = ` 727, 728, ], - "id": 371, + "id": 372, "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "man_dir": "", "name": "string.prototype.trimstart", @@ -42013,7 +42298,25 @@ exports[`next build works: node 1`] = ` "dependencies": [ 729, ], - "id": 372, + "id": 373, + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "man_dir": "", + "name": "strip-ansi", + "name_hash": "13340235767065158173", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "tag": "npm", + "value": "6.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 730, + ], + "id": 374, "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "man_dir": "", "name": "strip-ansi", @@ -42029,7 +42332,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 373, + "id": 375, "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "man_dir": "", "name": "strip-bom", @@ -42045,7 +42348,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 374, + "id": 376, "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "man_dir": "", "name": "strip-json-comments", @@ -42064,7 +42367,7 @@ exports[`next build works: node 1`] = ` 731, 732, ], - "id": 375, + "id": 377, "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", "man_dir": "", "name": "styled-jsx", @@ -42091,7 +42394,7 @@ exports[`next build works: node 1`] = ` 738, 739, ], - "id": 376, + "id": 378, "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "man_dir": "", "name": "sucrase", @@ -42109,7 +42412,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 740, ], - "id": 377, + "id": 379, "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "man_dir": "", "name": "supports-color", @@ -42125,7 +42428,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 378, + "id": 380, "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "man_dir": "", "name": "supports-preserve-symlinks-flag", @@ -42167,7 +42470,7 @@ exports[`next build works: node 1`] = ` 761, 762, ], - "id": 379, + "id": 381, "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", "man_dir": "", "name": "tailwindcss", @@ -42183,7 +42486,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 380, + "id": 382, "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "man_dir": "", "name": "tapable", @@ -42204,7 +42507,7 @@ exports[`next build works: node 1`] = ` 765, 766, ], - "id": 381, + "id": 383, "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", "man_dir": "", "name": "tar-fs", @@ -42224,7 +42527,7 @@ exports[`next build works: node 1`] = ` 768, 769, ], - "id": 382, + "id": 384, "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "man_dir": "", "name": "tar-stream", @@ -42242,7 +42545,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 770, ], - "id": 383, + "id": 385, "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", "man_dir": "", "name": "text-decoder", @@ -42258,7 +42561,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 384, + "id": 386, "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "man_dir": "", "name": "text-table", @@ -42276,7 +42579,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 771, ], - "id": 385, + "id": 387, "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "man_dir": "", "name": "thenify", @@ -42294,7 +42597,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 772, ], - "id": 386, + "id": 388, "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "man_dir": "", "name": "thenify-all", @@ -42310,7 +42613,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 387, + "id": 389, "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "man_dir": "", "name": "through", @@ -42328,7 +42631,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 773, ], - "id": 388, + "id": 390, "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "man_dir": "", "name": "to-regex-range", @@ -42346,7 +42649,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 774, ], - "id": 389, + "id": 391, "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "man_dir": "", "name": "ts-api-utils", @@ -42362,7 +42665,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 390, + "id": 392, "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "man_dir": "", "name": "ts-interface-checker", @@ -42383,7 +42686,7 @@ exports[`next build works: node 1`] = ` 777, 778, ], - "id": 391, + "id": 393, "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "man_dir": "", "name": "tsconfig-paths", @@ -42399,7 +42702,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 392, + "id": 394, "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "man_dir": "", "name": "tslib", @@ -42417,7 +42720,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 779, ], - "id": 393, + "id": 395, "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "man_dir": "", "name": "type-check", @@ -42433,7 +42736,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 394, + "id": 396, "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "man_dir": "", "name": "type-fest", @@ -42453,7 +42756,7 @@ exports[`next build works: node 1`] = ` 781, 782, ], - "id": 395, + "id": 397, "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "man_dir": "", "name": "typed-array-buffer", @@ -42475,7 +42778,7 @@ exports[`next build works: node 1`] = ` 786, 787, ], - "id": 396, + "id": 398, "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "man_dir": "", "name": "typed-array-byte-length", @@ -42498,7 +42801,7 @@ exports[`next build works: node 1`] = ` 792, 793, ], - "id": 397, + "id": 399, "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "man_dir": "", "name": "typed-array-byte-offset", @@ -42521,7 +42824,7 @@ exports[`next build works: node 1`] = ` 798, 799, ], - "id": 398, + "id": 400, "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "man_dir": "", "name": "typed-array-length", @@ -42540,7 +42843,7 @@ exports[`next build works: node 1`] = ` "tsserver": "bin/tsserver", }, "dependencies": [], - "id": 399, + "id": 401, "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "man_dir": "", "name": "typescript", @@ -42561,7 +42864,7 @@ exports[`next build works: node 1`] = ` 802, 803, ], - "id": 400, + "id": 402, "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "man_dir": "", "name": "unbox-primitive", @@ -42580,7 +42883,7 @@ exports[`next build works: node 1`] = ` 804, 805, ], - "id": 401, + "id": 403, "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "man_dir": "", "name": "unbzip2-stream", @@ -42596,7 +42899,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 402, + "id": 404, "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "man_dir": "", "name": "undici-types", @@ -42612,7 +42915,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 403, + "id": 405, "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "man_dir": "", "name": "universalify", @@ -42635,7 +42938,7 @@ exports[`next build works: node 1`] = ` 807, 808, ], - "id": 404, + "id": 406, "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "man_dir": "", "name": "update-browserslist-db", @@ -42653,7 +42956,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 809, ], - "id": 405, + "id": 407, "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "man_dir": "", "name": "uri-js", @@ -42669,7 +42972,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 406, + "id": 408, "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", "man_dir": "", "name": "urlpattern-polyfill", @@ -42685,7 +42988,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 407, + "id": 409, "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "man_dir": "", "name": "util-deprecate", @@ -42706,7 +43009,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 810, ], - "id": 408, + "id": 410, "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "man_dir": "", "name": "which", @@ -42728,7 +43031,7 @@ exports[`next build works: node 1`] = ` 814, 815, ], - "id": 409, + "id": 411, "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "man_dir": "", "name": "which-boxed-primitive", @@ -42757,7 +43060,7 @@ exports[`next build works: node 1`] = ` 826, 827, ], - "id": 410, + "id": 412, "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", "man_dir": "", "name": "which-builtin-type", @@ -42778,7 +43081,7 @@ exports[`next build works: node 1`] = ` 830, 831, ], - "id": 411, + "id": 413, "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "man_dir": "", "name": "which-collection", @@ -42800,7 +43103,7 @@ exports[`next build works: node 1`] = ` 835, 836, ], - "id": 412, + "id": 414, "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "man_dir": "", "name": "which-typed-array", @@ -42816,7 +43119,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 413, + "id": 415, "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "man_dir": "", "name": "word-wrap", @@ -42836,7 +43139,27 @@ exports[`next build works: node 1`] = ` 838, 839, ], - "id": 414, + "id": 416, + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "man_dir": "", + "name": "wrap-ansi", + "name_hash": "6417752039399150421", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "tag": "npm", + "value": "7.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 840, + 841, + 842, + ], + "id": 417, "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "man_dir": "", "name": "wrap-ansi", @@ -42852,7 +43175,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 415, + "id": 418, "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "man_dir": "", "name": "wrappy", @@ -42871,7 +43194,7 @@ exports[`next build works: node 1`] = ` 843, 844, ], - "id": 416, + "id": 419, "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "man_dir": "", "name": "ws", @@ -42887,7 +43210,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 417, + "id": 420, "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "man_dir": "", "name": "y18n", @@ -42903,7 +43226,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 418, + "id": 421, "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "man_dir": "", "name": "yallist", @@ -42922,7 +43245,7 @@ exports[`next build works: node 1`] = ` "name": "yaml", }, "dependencies": [], - "id": 419, + "id": 422, "integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==", "man_dir": "", "name": "yaml", @@ -42946,7 +43269,7 @@ exports[`next build works: node 1`] = ` 850, 851, ], - "id": 420, + "id": 423, "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "man_dir": "", "name": "yargs", @@ -42962,7 +43285,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 421, + "id": 424, "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "man_dir": "", "name": "yargs-parser", @@ -42981,7 +43304,7 @@ exports[`next build works: node 1`] = ` 852, 853, ], - "id": 422, + "id": 425, "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "man_dir": "", "name": "yauzl", @@ -42997,7 +43320,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 423, + "id": 426, "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "man_dir": "", "name": "yocto-queue", @@ -43013,7 +43336,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 424, + "id": 427, "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "man_dir": "", "name": "zod", @@ -43033,7 +43356,7 @@ exports[`next build works: node 1`] = ` 855, 856, ], - "id": 425, + "id": 428, "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "man_dir": "", "name": "chalk", @@ -43053,7 +43376,7 @@ exports[`next build works: node 1`] = ` 858, 859, ], - "id": 426, + "id": 429, "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "man_dir": "", "name": "string-width", @@ -43071,7 +43394,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 860, ], - "id": 427, + "id": 430, "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "man_dir": "", "name": "strip-ansi", @@ -43091,7 +43414,7 @@ exports[`next build works: node 1`] = ` 862, 863, ], - "id": 428, + "id": 431, "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "man_dir": "", "name": "wrap-ansi", @@ -43109,7 +43432,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 864, ], - "id": 429, + "id": 432, "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "man_dir": "", "name": "debug", @@ -43130,7 +43453,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 865, ], - "id": 430, + "id": 433, "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "man_dir": "", "name": "semver", @@ -43148,7 +43471,25 @@ exports[`next build works: node 1`] = ` "dependencies": [ 866, ], - "id": 431, + "id": 434, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 867, + ], + "id": 435, "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", "man_dir": "", "name": "@types/node", @@ -43166,7 +43507,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 868, ], - "id": 432, + "id": 436, "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "man_dir": "", "name": "minimatch", @@ -43179,12 +43520,51 @@ exports[`next build works: node 1`] = ` }, "scripts": {}, }, + { + "bin": { + "file": "bin/semver.js", + "name": "semver", + }, + "dependencies": [ + 869, + ], + "id": 437, + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "man_dir": "", + "name": "semver", + "name_hash": "16367367531761322261", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "tag": "npm", + "value": "7.6.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 870, + ], + "id": 438, + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "man_dir": "", + "name": "@types/node", + "name_hash": "4124652010926124945", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "tag": "npm", + "value": "20.12.14", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ 871, ], - "id": 433, + "id": 439, "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "man_dir": "", "name": "glob-parent", @@ -43202,7 +43582,43 @@ exports[`next build works: node 1`] = ` "dependencies": [ 872, ], - "id": 434, + "id": 440, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 873, + ], + "id": 441, + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "man_dir": "", + "name": "debug", + "name_hash": "14324291119347696526", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "tag": "npm", + "value": "3.2.7", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 874, + ], + "id": 442, "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "man_dir": "", "name": "debug", @@ -43220,7 +43636,25 @@ exports[`next build works: node 1`] = ` "dependencies": [ 875, ], - "id": 435, + "id": 443, + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "man_dir": "", + "name": "doctrine", + "name_hash": "17204823894354646410", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "tag": "npm", + "value": "2.1.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 876, + ], + "id": 444, "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "man_dir": "", "name": "doctrine", @@ -43243,7 +43677,7 @@ exports[`next build works: node 1`] = ` 878, 879, ], - "id": 436, + "id": 445, "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "man_dir": "", "name": "resolve", @@ -43256,12 +43690,30 @@ exports[`next build works: node 1`] = ` }, "scripts": {}, }, + { + "bin": null, + "dependencies": [ + 880, + ], + "id": 446, + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "man_dir": "", + "name": "glob-parent", + "name_hash": "11965780159102682782", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "tag": "npm", + "value": "5.1.2", + }, + "scripts": {}, + }, { "bin": null, "dependencies": [ 881, ], - "id": 437, + "id": 447, "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "man_dir": "", "name": "minimatch", @@ -43281,7 +43733,7 @@ exports[`next build works: node 1`] = ` 883, 884, ], - "id": 438, + "id": 448, "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "man_dir": "", "name": "postcss", @@ -43297,7 +43749,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 439, + "id": 449, "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "man_dir": "", "name": "lru-cache", @@ -43313,7 +43765,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 440, + "id": 450, "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "man_dir": "", "name": "lilconfig", @@ -43336,7 +43788,7 @@ exports[`next build works: node 1`] = ` 889, 890, ], - "id": 441, + "id": 451, "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "man_dir": "", "name": "glob", @@ -43352,7 +43804,23 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 442, + "id": 452, + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "man_dir": "", + "name": "emoji-regex", + "name_hash": "4954026511424972012", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "tag": "npm", + "value": "8.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [], + "id": 453, "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "man_dir": "", "name": "emoji-regex", @@ -43370,7 +43838,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 891, ], - "id": 443, + "id": 454, "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "man_dir": "", "name": "ansi-styles", @@ -43386,7 +43854,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 444, + "id": 455, "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "man_dir": "", "name": "escape-string-regexp", @@ -43404,7 +43872,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 892, ], - "id": 445, + "id": 456, "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "man_dir": "", "name": "supports-color", @@ -43420,7 +43888,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 446, + "id": 457, "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "man_dir": "", "name": "ansi-regex", @@ -43436,7 +43904,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 447, + "id": 458, "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "man_dir": "", "name": "ansi-styles", @@ -43454,7 +43922,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 893, ], - "id": 448, + "id": 459, "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "man_dir": "", "name": "lru-cache", @@ -43472,7 +43940,43 @@ exports[`next build works: node 1`] = ` "dependencies": [ 894, ], - "id": 449, + "id": 460, + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "man_dir": "", + "name": "brace-expansion", + "name_hash": "2949258092693339993", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "tag": "npm", + "value": "2.0.1", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 895, + ], + "id": 461, + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "man_dir": "", + "name": "lru-cache", + "name_hash": "15261810304153928944", + "origin": "npm", + "resolution": { + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "tag": "npm", + "value": "6.0.0", + }, + "scripts": {}, + }, + { + "bin": null, + "dependencies": [ + 896, + ], + "id": 462, "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "man_dir": "", "name": "brace-expansion", @@ -43490,7 +43994,7 @@ exports[`next build works: node 1`] = ` "dependencies": [ 897, ], - "id": 450, + "id": 463, "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "man_dir": "", "name": "color-convert", @@ -43506,7 +44010,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 451, + "id": 464, "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "man_dir": "", "name": "has-flag", @@ -43522,7 +44026,7 @@ exports[`next build works: node 1`] = ` { "bin": null, "dependencies": [], - "id": 452, + "id": 465, "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "man_dir": "", "name": "color-name", @@ -45009,243 +45513,243 @@ exports[`next build works: node 1`] = ` }, "string-width-cjs": { "id": 36, - "package_id": 367, + "package_id": 368, }, "string.prototype.matchall": { "id": 409, - "package_id": 368, + "package_id": 369, }, "string.prototype.trim": { "id": 259, - "package_id": 369, + "package_id": 370, }, "string.prototype.trimend": { "id": 260, - "package_id": 370, + "package_id": 371, }, "string.prototype.trimstart": { "id": 261, - "package_id": 371, + "package_id": 372, }, "strip-ansi": { "id": 330, - "package_id": 372, + "package_id": 373, }, "strip-ansi-cjs": { "id": 38, - "package_id": 372, + "package_id": 374, }, "strip-bom": { "id": 778, - "package_id": 373, + "package_id": 375, }, "strip-json-comments": { "id": 31, - "package_id": 374, + "package_id": 376, }, "styled-jsx": { "id": 561, - "package_id": 375, + "package_id": 377, }, "sucrase": { "id": 762, - "package_id": 376, + "package_id": 378, }, "supports-color": { "id": 172, - "package_id": 377, + "package_id": 379, }, "supports-preserve-symlinks-flag": { "id": 666, - "package_id": 378, + "package_id": 380, }, "tailwindcss": { "id": 12, - "package_id": 379, + "package_id": 381, }, "tapable": { "id": 220, - "package_id": 380, + "package_id": 382, }, "tar-fs": { "id": 56, - "package_id": 381, + "package_id": 383, }, "tar-stream": { "id": 766, - "package_id": 382, + "package_id": 384, }, "text-decoder": { "id": 700, - "package_id": 383, + "package_id": 385, }, "text-table": { "id": 331, - "package_id": 384, + "package_id": 386, }, "thenify": { "id": 772, - "package_id": 385, + "package_id": 387, }, "thenify-all": { "id": 541, - "package_id": 386, + "package_id": 388, }, "through": { "id": 805, - "package_id": 387, + "package_id": 389, }, "to-regex-range": { "id": 430, - "package_id": 388, + "package_id": 390, }, "ts-api-utils": { "id": 81, - "package_id": 389, + "package_id": 391, }, "ts-interface-checker": { "id": 739, - "package_id": 390, + "package_id": 392, }, "tsconfig-paths": { "id": 373, - "package_id": 391, + "package_id": 393, }, "tslib": { "id": 59, - "package_id": 392, + "package_id": 394, }, "type-check": { "id": 533, - "package_id": 393, + "package_id": 395, }, "type-fest": { "id": 466, - "package_id": 394, + "package_id": 396, }, "typed-array-buffer": { "id": 262, - "package_id": 395, + "package_id": 397, }, "typed-array-byte-length": { "id": 263, - "package_id": 396, + "package_id": 398, }, "typed-array-byte-offset": { "id": 264, - "package_id": 397, + "package_id": 399, }, "typed-array-length": { "id": 265, - "package_id": 398, + "package_id": 400, }, "typescript": { "id": 13, - "package_id": 399, + "package_id": 401, }, "unbox-primitive": { "id": 266, - "package_id": 400, + "package_id": 402, }, "unbzip2-stream": { "id": 57, - "package_id": 401, + "package_id": 403, }, "undici-types": { - "id": 866, - "package_id": 402, + "id": 870, + "package_id": 404, }, "universalify": { "id": 441, - "package_id": 403, + "package_id": 405, }, "update-browserslist-db": { "id": 160, - "package_id": 404, + "package_id": 406, }, "uri-js": { "id": 89, - "package_id": 405, + "package_id": 407, }, "urlpattern-polyfill": { "id": 183, - "package_id": 406, + "package_id": 408, }, "util-deprecate": { "id": 624, - "package_id": 407, + "package_id": 409, }, "which": { "id": 196, - "package_id": 408, + "package_id": 410, }, "which-boxed-primitive": { "id": 803, - "package_id": 409, + "package_id": 411, }, "which-builtin-type": { "id": 659, - "package_id": 410, + "package_id": 412, }, "which-collection": { "id": 826, - "package_id": 411, + "package_id": 413, }, "which-typed-array": { "id": 267, - "package_id": 412, + "package_id": 414, }, "word-wrap": { "id": 588, - "package_id": 413, + "package_id": 415, }, "wrap-ansi": { "id": 187, - "package_id": 414, + "package_id": 416, }, "wrap-ansi-cjs": { "id": 40, - "package_id": 414, + "package_id": 417, }, "wrappy": { "id": 582, - "package_id": 415, + "package_id": 418, }, "ws": { "id": 646, - "package_id": 416, + "package_id": 419, }, "y18n": { "id": 850, - "package_id": 417, + "package_id": 420, }, "yallist": { "id": 893, - "package_id": 418, + "package_id": 421, }, "yaml": { "id": 620, - "package_id": 419, + "package_id": 422, }, "yargs": { "id": 58, - "package_id": 420, + "package_id": 423, }, "yargs-parser": { "id": 851, - "package_id": 421, + "package_id": 424, }, "yauzl": { "id": 421, - "package_id": 422, + "package_id": 425, }, "yocto-queue": { "id": 589, - "package_id": 423, + "package_id": 426, }, "zod": { "id": 184, - "package_id": 424, + "package_id": 427, }, }, "depth": 0, @@ -45256,7 +45760,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "@types/node": { "id": 163, - "package_id": 431, + "package_id": 438, }, }, "depth": 1, @@ -45267,7 +45771,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "postcss": { "id": 560, - "package_id": 438, + "package_id": 448, }, }, "depth": 1, @@ -45278,7 +45782,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "@types/node": { "id": 64, - "package_id": 431, + "package_id": 434, }, }, "depth": 1, @@ -45289,7 +45793,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "debug": { "id": 343, - "package_id": 434, + "package_id": 440, }, }, "depth": 1, @@ -45300,11 +45804,11 @@ exports[`next build works: node 1`] = ` "dependencies": { "debug": { "id": 361, - "package_id": 434, + "package_id": 442, }, "doctrine": { "id": 362, - "package_id": 435, + "package_id": 443, }, }, "depth": 1, @@ -45315,11 +45819,11 @@ exports[`next build works: node 1`] = ` "dependencies": { "doctrine": { "id": 397, - "package_id": 435, + "package_id": 444, }, "resolve": { "id": 407, - "package_id": 436, + "package_id": 445, }, }, "depth": 1, @@ -45330,11 +45834,11 @@ exports[`next build works: node 1`] = ` "dependencies": { "debug": { "id": 51, - "package_id": 429, + "package_id": 432, }, "semver": { "id": 55, - "package_id": 430, + "package_id": 433, }, }, "depth": 1, @@ -45345,7 +45849,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "glob-parent": { "id": 176, - "package_id": 433, + "package_id": 439, }, }, "depth": 1, @@ -45356,7 +45860,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "glob-parent": { "id": 424, - "package_id": 433, + "package_id": 446, }, }, "depth": 1, @@ -45367,7 +45871,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "lilconfig": { "id": 619, - "package_id": 440, + "package_id": 450, }, }, "depth": 1, @@ -45378,7 +45882,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "minimatch": { "id": 462, - "package_id": 437, + "package_id": 447, }, }, "depth": 1, @@ -45389,11 +45893,11 @@ exports[`next build works: node 1`] = ` "dependencies": { "minimatch": { "id": 79, - "package_id": 432, + "package_id": 436, }, "semver": { "id": 80, - "package_id": 430, + "package_id": 437, }, }, "depth": 1, @@ -45404,7 +45908,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "debug": { "id": 355, - "package_id": 434, + "package_id": 441, }, }, "depth": 1, @@ -45415,7 +45919,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "lru-cache": { "id": 865, - "package_id": 448, + "package_id": 459, }, }, "depth": 2, @@ -45426,7 +45930,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "glob": { "id": 667, - "package_id": 441, + "package_id": 451, }, }, "depth": 1, @@ -45437,7 +45941,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "brace-expansion": { "id": 881, - "package_id": 449, + "package_id": 462, }, }, "depth": 2, @@ -45448,7 +45952,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "lru-cache": { "id": 606, - "package_id": 439, + "package_id": 449, }, }, "depth": 1, @@ -45459,7 +45963,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "brace-expansion": { "id": 868, - "package_id": 449, + "package_id": 460, }, }, "depth": 2, @@ -45469,8 +45973,8 @@ exports[`next build works: node 1`] = ` { "dependencies": { "lru-cache": { - "id": 865, - "package_id": 448, + "id": 869, + "package_id": 461, }, }, "depth": 2, @@ -45481,7 +45985,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "@types/node": { "id": 65, - "package_id": 431, + "package_id": 435, }, }, "depth": 1, @@ -45492,7 +45996,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "emoji-regex": { "id": 701, - "package_id": 442, + "package_id": 452, }, }, "depth": 1, @@ -45503,15 +46007,15 @@ exports[`next build works: node 1`] = ` "dependencies": { "string-width": { "id": 35, - "package_id": 426, + "package_id": 429, }, "strip-ansi": { "id": 37, - "package_id": 427, + "package_id": 430, }, "wrap-ansi": { "id": 39, - "package_id": 428, + "package_id": 431, }, }, "depth": 1, @@ -45522,7 +46026,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "chalk": { "id": 17, - "package_id": 425, + "package_id": 428, }, }, "depth": 1, @@ -45532,8 +46036,8 @@ exports[`next build works: node 1`] = ` { "dependencies": { "emoji-regex": { - "id": 701, - "package_id": 442, + "id": 704, + "package_id": 453, }, }, "depth": 1, @@ -45544,7 +46048,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "ansi-regex": { "id": 860, - "package_id": 446, + "package_id": 457, }, }, "depth": 2, @@ -45555,7 +46059,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "ansi-styles": { "id": 861, - "package_id": 447, + "package_id": 458, }, }, "depth": 2, @@ -45566,15 +46070,15 @@ exports[`next build works: node 1`] = ` "dependencies": { "ansi-styles": { "id": 854, - "package_id": 443, + "package_id": 454, }, "escape-string-regexp": { "id": 855, - "package_id": 444, + "package_id": 455, }, "supports-color": { "id": 856, - "package_id": 445, + "package_id": 456, }, }, "depth": 2, @@ -45585,7 +46089,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "color-convert": { "id": 891, - "package_id": 450, + "package_id": 463, }, }, "depth": 3, @@ -45596,7 +46100,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "has-flag": { "id": 892, - "package_id": 451, + "package_id": 464, }, }, "depth": 3, @@ -45607,7 +46111,7 @@ exports[`next build works: node 1`] = ` "dependencies": { "color-name": { "id": 897, - "package_id": 452, + "package_id": 465, }, }, "depth": 4, diff --git a/test/integration/vite-build/the-test-app/app/app.d.ts b/test/integration/vite-build/the-test-app/app/app.d.ts new file mode 100644 index 00000000000000..5a485ac61ee8eb --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/app.d.ts @@ -0,0 +1,53 @@ +import "svelte/elements"; + +import type { Message } from "$lib/types"; + +export interface AnalyticsWorker extends Worker { + postMessage(message: Message): void; +} + +declare global { + namespace App { + interface Error { + status?: number; + message: string; + } + + interface PageState { + page?: number; + searchOpen?: boolean; + readerPreferencesOpen?: boolean; + } + + interface Locals { + user: import("lucia").User | null; + session: import("lucia").Session | null; + analytics?: AnalyticsWorker; + } + } + + declare module "*?raw-hex" { + const src: string; + export default src; + } + + interface Uint8ArrayConstructor { + fromHex: (hex: string) => Uint8Array; + } + + namespace svelteHTML { + interface HTMLAttributes { + "on:dropItem"?: (event: CustomEvent) => void; + } + } +} + +declare module "svelte/elements" { + interface HTMLAttributes + extends AriaAttributes, + DOMAttributes { + tw?: string; + } +} + +export {}; diff --git a/test/integration/vite-build/the-test-app/app/app.html b/test/integration/vite-build/the-test-app/app/app.html new file mode 100644 index 00000000000000..2e3860765fd024 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/app.html @@ -0,0 +1,13 @@ + + + + + + + %sveltekit.head% + + + +
%sveltekit.body%
+ + diff --git a/test/integration/vite-build/the-test-app/app/app.pcss b/test/integration/vite-build/the-test-app/app/app.pcss new file mode 100644 index 00000000000000..2d873a85a7d61f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/app.pcss @@ -0,0 +1,112 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 3.9%; + --foreground: 0 0% 90%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 95%; + --primary: 0 72.2% 50.6%; + --primary-foreground: 0 85.7% 97.3%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 10%; + --muted-foreground: 0 0% 63.9%; + --muted-foreground-light: 0 0% 85%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 72.2% 30.6%; + --radius: 0.5rem; + --shadow: 0 0 10%; + --blur: 8px; + + font-family: "Inter", ui-sans-serif, system-ui, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + "Noto Color Emoji"; + } +} + +@layer base { + * { + @apply border-border; + } + + body { + @apply bg-background text-foreground; + } +} + +::-webkit-search-cancel-button { + display: none; +} + +main { + @apply p-2 duration-150 lg:p-3; +} + +.toast div[data-content] { + width: 100%; +} + +.stroke { + text-shadow: + 1px 1px 0 #000, + -1px -1px 0 #000, + 1px -1px 0 #000, + -1px 1px 0 #000, + 1px 1px 0 #000; +} + +.scroller { + --scrollbar-color-track: #0000ff; + --scrollbar-color-thumb: #ff69b4; +} + +@supports (scrollbar-width: auto) { + .scroller { + scrollbar-color: hsl(var(--muted-foreground)) hsl(var(--secondary)); + } + + .warning { + display: none; + } +} + +.scroller { + border: 1px solid #000; + width: 100%; + height: 50vh; + + position: relative; + container-type: inline-size; + + &:has(.content) { + background: white; + overflow-y: auto; + overscroll-behavior: contain; + } + + .content { + min-height: 75vh; + padding: 1rem 1rem; + + *:first-child { + margin-top: 0; + } + *:last-child { + margin-bottom: 0; + } + } +} + +.toaster.group:where([data-sonner-toaster]) { + z-index: 100; +} diff --git a/test/integration/vite-build/the-test-app/app/lib/components/login-form.svelte b/test/integration/vite-build/the-test-app/app/lib/components/login-form.svelte new file mode 100644 index 00000000000000..9b7340b11c43c5 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/login-form.svelte @@ -0,0 +1,89 @@ + + +
+
+ + + Username + + + + + + + + Password + + + + +
+ +
+ + + +
+ + Login +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/recover-form.svelte b/test/integration/vite-build/the-test-app/app/lib/components/recover-form.svelte new file mode 100644 index 00000000000000..fdf603797239e3 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/recover-form.svelte @@ -0,0 +1,96 @@ + + +
+ {#if hasMailer} +
+ + + Username + + + + +
+ {:else} +

+ The site can't send emails.
Make a request to the admin for a recovery code. +

+ {/if} + +
+ + + +
+ + Recover + + +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/register-form.svelte b/test/integration/vite-build/the-test-app/app/lib/components/register-form.svelte new file mode 100644 index 00000000000000..0b4f225c84a140 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/register-form.svelte @@ -0,0 +1,112 @@ + + +
+
+ + + Username + + + + + + + + Password + + + + + + + + Confirm Password + + + + + + + + + Email (optional) + + + + + +
+ +
+ + + +
+ + Create Account +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/reset-form.svelte b/test/integration/vite-build/the-test-app/app/lib/components/reset-form.svelte new file mode 100644 index 00000000000000..444296d976851b --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/reset-form.svelte @@ -0,0 +1,115 @@ + + +
+
+ + + New Password + + + + + + + + Confirm Password + + + + + + + + Recovery code + + + + +
+ +
+ + +
+ + Reset Password + + +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-action.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-action.svelte new file mode 100644 index 00000000000000..2c5ea4c0af21fd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-action.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte new file mode 100644 index 00000000000000..edf6d78da90c46 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-content.svelte new file mode 100644 index 00000000000000..0d1ebace7f611c --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-content.svelte @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-description.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-description.svelte new file mode 100644 index 00000000000000..c77c68409ee4cc --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-description.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-footer.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-footer.svelte new file mode 100644 index 00000000000000..329304a8f2fefc --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-footer.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-header.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-header.svelte new file mode 100644 index 00000000000000..434c29c978b982 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-header.svelte @@ -0,0 +1,13 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte new file mode 100644 index 00000000000000..4c3ca88d44ba22 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte @@ -0,0 +1,21 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-portal.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-portal.svelte new file mode 100644 index 00000000000000..347119a27a3658 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-portal.svelte @@ -0,0 +1,9 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-title.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-title.svelte new file mode 100644 index 00000000000000..75287f36856e2f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/alert-dialog-title.svelte @@ -0,0 +1,14 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/index.ts new file mode 100644 index 00000000000000..2cdf713268e676 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert-dialog/index.ts @@ -0,0 +1,40 @@ +import { AlertDialog as AlertDialogPrimitive } from "bits-ui"; + +import Action from "./alert-dialog-action.svelte"; +import Cancel from "./alert-dialog-cancel.svelte"; +import Content from "./alert-dialog-content.svelte"; +import Description from "./alert-dialog-description.svelte"; +import Footer from "./alert-dialog-footer.svelte"; +import Header from "./alert-dialog-header.svelte"; +import Overlay from "./alert-dialog-overlay.svelte"; +import Portal from "./alert-dialog-portal.svelte"; +import Title from "./alert-dialog-title.svelte"; + +const Root = AlertDialogPrimitive.Root; +const Trigger = AlertDialogPrimitive.Trigger; + +export { + Action, + // + Root as AlertDialog, + Action as AlertDialogAction, + Cancel as AlertDialogCancel, + Content as AlertDialogContent, + Description as AlertDialogDescription, + Footer as AlertDialogFooter, + Header as AlertDialogHeader, + Overlay as AlertDialogOverlay, + Portal as AlertDialogPortal, + Title as AlertDialogTitle, + Trigger as AlertDialogTrigger, + Cancel, + Content, + Description, + Footer, + Header, + Overlay, + Portal, + Root, + Title, + Trigger, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert-description.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert-description.svelte new file mode 100644 index 00000000000000..06d344cc33771e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert-description.svelte @@ -0,0 +1,13 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert-title.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert-title.svelte new file mode 100644 index 00000000000000..c63089bde4f4ff --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert-title.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert.svelte new file mode 100644 index 00000000000000..0bf6eec74d3c95 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/alert.svelte @@ -0,0 +1,17 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/index.ts new file mode 100644 index 00000000000000..8f11bb0b15808e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/alert/index.ts @@ -0,0 +1,33 @@ +import { type VariantProps, tv } from "tailwind-variants"; + +import Description from "./alert-description.svelte"; +import Title from "./alert-title.svelte"; +import Root from "./alert.svelte"; + +export const alertVariants = tv({ + base: "[&>svg]:text-foreground relative w-full rounded-lg border p-4 [&:has(svg)]:pl-11 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4", + + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, +}); + +export type Variant = VariantProps["variant"]; +export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; + +export { + // + Root as Alert, + Description as AlertDescription, + Title as AlertTitle, + Description, + Root, + Title, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/button/button.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/button/button.svelte new file mode 100644 index 00000000000000..8c1daf08efb987 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/button/button.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/button/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/button/index.ts new file mode 100644 index 00000000000000..bd04ea454a7396 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/button/index.ts @@ -0,0 +1,63 @@ +import type { Button as ButtonPrimitive } from "bits-ui"; +import { tv, type VariantProps } from "tailwind-variants"; +import Root from "./button.svelte"; + +const buttonVariants = tv({ + base: "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + "primary-outline": + "border border-primary/50 bg-transparent text-foreground hover:bg-primary/20", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + indigo: "bg-indigo-700 text-foreground hover:bg-indigo-700/90", + "indigo-outline": + "border border-indigo-700/50 bg-transparent text-foreground hover:bg-indigo-700/20", + sky: "bg-sky-700 text-foreground hover:bg-sky-700/90", + "sky-outline": + "border border-sky-700/50 bg-transparent text-foreground hover:bg-sky-700/20", + "blue-outline": + "border border-blue-700/50 bg-transparent text-foreground hover:bg-blue-700/20", + "green-outline": + "border border-green-700/50 bg-transparent text-foreground hover:bg-green-700/20", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: + "hover:bg-accent/90 active:bg-accent hover:text-accent-foreground/90 active:text-accent-foreground focus-visible:bg-accent", + link: "text-foreground underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +type Variant = VariantProps["variant"]; +type Size = VariantProps["size"]; + +type Props = ButtonPrimitive.Props & { + variant?: Variant; + size?: Size; +}; + +type Events = ButtonPrimitive.Events; + +export { + // + Root as Button, + buttonVariants, + Root, + type Events as ButtonEvents, + type Props as ButtonProps, + type Events, + type Props, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-cell.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-cell.svelte new file mode 100644 index 00000000000000..1a1cd7ee30b827 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-cell.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-day.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-day.svelte new file mode 100644 index 00000000000000..273edfd859e2ec --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-day.svelte @@ -0,0 +1,42 @@ + + + + + {date.day} + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-body.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-body.svelte new file mode 100644 index 00000000000000..42f96f0d4f7ef7 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-body.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-head.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-head.svelte new file mode 100644 index 00000000000000..f7e0d9cc2cbe28 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-head.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-row.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-row.svelte new file mode 100644 index 00000000000000..3a59498cdc568f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid-row.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid.svelte new file mode 100644 index 00000000000000..df284112cfbf6c --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-grid.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-head-cell.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-head-cell.svelte new file mode 100644 index 00000000000000..0c97f326678143 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-head-cell.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-header.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-header.svelte new file mode 100644 index 00000000000000..2ebaa4992822fb --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-header.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-heading.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-heading.svelte new file mode 100644 index 00000000000000..9007c53443bd43 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-heading.svelte @@ -0,0 +1,19 @@ + + + + + {headingValue} + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-months.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-months.svelte new file mode 100644 index 00000000000000..9ce632886b9183 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-months.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-next-button.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-next-button.svelte new file mode 100644 index 00000000000000..73fd72a2c901cd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-next-button.svelte @@ -0,0 +1,27 @@ + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-prev-button.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-prev-button.svelte new file mode 100644 index 00000000000000..50055805002e8a --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar-prev-button.svelte @@ -0,0 +1,27 @@ + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar.svelte new file mode 100644 index 00000000000000..f53b2c2c9b343d --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/calendar.svelte @@ -0,0 +1,59 @@ + + + + + + + + + + {#each months as month} + + + + {#each weekdays as weekday} + + {weekday.slice(0, 2)} + + {/each} + + + + {#each month.weeks as weekDates} + + {#each weekDates as date} + + + + {/each} + + {/each} + + + {/each} + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/index.ts new file mode 100644 index 00000000000000..9356541f973bfd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/calendar/index.ts @@ -0,0 +1,30 @@ +import Cell from "./calendar-cell.svelte"; +import Day from "./calendar-day.svelte"; +import GridBody from "./calendar-grid-body.svelte"; +import GridHead from "./calendar-grid-head.svelte"; +import GridRow from "./calendar-grid-row.svelte"; +import Grid from "./calendar-grid.svelte"; +import HeadCell from "./calendar-head-cell.svelte"; +import Header from "./calendar-header.svelte"; +import Heading from "./calendar-heading.svelte"; +import Months from "./calendar-months.svelte"; +import NextButton from "./calendar-next-button.svelte"; +import PrevButton from "./calendar-prev-button.svelte"; +import Root from "./calendar.svelte"; + +export { + // + Root as Calendar, + Cell, + Day, + Grid, + GridBody, + GridHead, + GridRow, + HeadCell, + Header, + Heading, + Months, + NextButton, + PrevButton, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/checkbox/checkbox.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/checkbox/checkbox.svelte new file mode 100644 index 00000000000000..c8464e03f850af --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/checkbox/checkbox.svelte @@ -0,0 +1,35 @@ + + + + + {#if isChecked} + + {:else if isIndeterminate} + + {/if} + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/checkbox/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/checkbox/index.ts new file mode 100644 index 00000000000000..b1ee0ed3167d17 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/checkbox/index.ts @@ -0,0 +1,6 @@ +import Root from "./checkbox.svelte"; +export { + // + Root as Checkbox, + Root, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-dialog.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-dialog.svelte new file mode 100644 index 00000000000000..bc705219354e06 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-dialog.svelte @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-empty.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-empty.svelte new file mode 100644 index 00000000000000..3c87766d2cdedd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-empty.svelte @@ -0,0 +1,12 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-group.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-group.svelte new file mode 100644 index 00000000000000..bc5c6910c1162f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-group.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-input.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-input.svelte new file mode 100644 index 00000000000000..baa65fef5703cd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-input.svelte @@ -0,0 +1,21 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-item.svelte new file mode 100644 index 00000000000000..5f691e622480d3 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-item.svelte @@ -0,0 +1,24 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-list.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-list.svelte new file mode 100644 index 00000000000000..cbe76d2339f589 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-list.svelte @@ -0,0 +1,15 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-separator.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-separator.svelte new file mode 100644 index 00000000000000..93bb3d5a1bd10b --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-separator.svelte @@ -0,0 +1,10 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-shortcut.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-shortcut.svelte new file mode 100644 index 00000000000000..9987b93e272a0d --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command-shortcut.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command.svelte new file mode 100644 index 00000000000000..b8cba5dfbf3120 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/command.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/command/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/index.ts new file mode 100644 index 00000000000000..1ed0811ca768e3 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/command/index.ts @@ -0,0 +1,37 @@ +import { Command as CommandPrimitive } from "cmdk-sv"; + +import Dialog from "./command-dialog.svelte"; +import Empty from "./command-empty.svelte"; +import Group from "./command-group.svelte"; +import Input from "./command-input.svelte"; +import Item from "./command-item.svelte"; +import List from "./command-list.svelte"; +import Separator from "./command-separator.svelte"; +import Shortcut from "./command-shortcut.svelte"; +import Root from "./command.svelte"; + +const Loading = CommandPrimitive.Loading; + +export { + // + Root as Command, + Dialog as CommandDialog, + Empty as CommandEmpty, + Group as CommandGroup, + Input as CommandInput, + Item as CommandItem, + List as CommandList, + Loading as CommandLoading, + Separator as CommandSeparator, + Shortcut as CommandShortcut, + Dialog, + Empty, + Group, + Input, + Item, + List, + Loading, + Root, + Separator, + Shortcut, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 00000000000000..1be424fd75db3b --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-description.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 00000000000000..84d4e5f1678950 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-footer.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 00000000000000..de907bafb35e5a --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-header.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 00000000000000..03667b794a6e21 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,13 @@ + + +
+ +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-overlay.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 00000000000000..bb007d08621cef --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,21 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-portal.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 00000000000000..00774dd4ca698d --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,8 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-title.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 00000000000000..c133166b342bd3 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/index.ts new file mode 100644 index 00000000000000..a0be3d6194845a --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dialog/index.ts @@ -0,0 +1,37 @@ +import { Dialog as DialogPrimitive } from "bits-ui"; + +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Portal from "./dialog-portal.svelte"; +import Title from "./dialog-title.svelte"; + +const Root = DialogPrimitive.Root; +const Trigger = DialogPrimitive.Trigger; +const Close = DialogPrimitive.Close; + +export { + Close, + Content, + Description, + // + Root as Dialog, + Close as DialogClose, + Content as DialogContent, + Description as DialogDescription, + Footer as DialogFooter, + Header as DialogHeader, + Overlay as DialogOverlay, + Portal as DialogPortal, + Title as DialogTitle, + Trigger as DialogTrigger, + Footer, + Header, + Overlay, + Portal, + Root, + Title, + Trigger, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 00000000000000..729503da9ef9fa --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 00000000000000..f1054415c70e0f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 00000000000000..1d5db0f015b697 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 00000000000000..670a6861bf17d7 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 00000000000000..dd67d44038f277 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,11 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 00000000000000..58d8ab6ea1609d --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 00000000000000..cc0197e2679f26 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,14 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 00000000000000..eeeb8f7e50295b --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 00000000000000..f647d9c93bfdfa --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,30 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 00000000000000..2f459f8645f216 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,32 @@ + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/index.ts new file mode 100644 index 00000000000000..8cf7428581e1fd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,48 @@ +import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui"; +import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; +import Content from "./dropdown-menu-content.svelte"; +import Item from "./dropdown-menu-item.svelte"; +import Label from "./dropdown-menu-label.svelte"; +import RadioGroup from "./dropdown-menu-radio-group.svelte"; +import RadioItem from "./dropdown-menu-radio-item.svelte"; +import Separator from "./dropdown-menu-separator.svelte"; +import Shortcut from "./dropdown-menu-shortcut.svelte"; +import SubContent from "./dropdown-menu-sub-content.svelte"; +import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; + +const Sub = DropdownMenuPrimitive.Sub; +const Root = DropdownMenuPrimitive.Root; +const Trigger = DropdownMenuPrimitive.Trigger; +const Group = DropdownMenuPrimitive.Group; + +export { + CheckboxItem, + Content, + // + Root as DropdownMenu, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Group as DropdownMenuGroup, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + Group, + Item, + Label, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-button.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-button.svelte new file mode 100644 index 00000000000000..8a14884301b63e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-button.svelte @@ -0,0 +1,10 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-description.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-description.svelte new file mode 100644 index 00000000000000..7d3aa4908a4f1e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-description.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-element-field.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-element-field.svelte new file mode 100644 index 00000000000000..a9ab42fd5c06cb --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-element-field.svelte @@ -0,0 +1,25 @@ + + + + + +
+ +
+
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-field-errors.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-field-errors.svelte new file mode 100644 index 00000000000000..ae9212c8e02c4e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-field-errors.svelte @@ -0,0 +1,26 @@ + + + + + {#each errors as error} +
{error}
+ {/each} +
+
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-field.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-field.svelte new file mode 100644 index 00000000000000..a0d5e0bda12734 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-field.svelte @@ -0,0 +1,25 @@ + + + + + +
+ +
+
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-fieldset.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-fieldset.svelte new file mode 100644 index 00000000000000..ff51b1a89c8ee3 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-fieldset.svelte @@ -0,0 +1,30 @@ + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-label.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-label.svelte new file mode 100644 index 00000000000000..977ae25aa0e528 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-label.svelte @@ -0,0 +1,17 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-legend.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-legend.svelte new file mode 100644 index 00000000000000..f8adaab5875b63 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/form-legend.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/form/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/index.ts new file mode 100644 index 00000000000000..0c88b1f6a89f27 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/form/index.ts @@ -0,0 +1,33 @@ +import * as FormPrimitive from "formsnap"; +import Button from "./form-button.svelte"; +import Description from "./form-description.svelte"; +import ElementField from "./form-element-field.svelte"; +import FieldErrors from "./form-field-errors.svelte"; +import Field from "./form-field.svelte"; +import Fieldset from "./form-fieldset.svelte"; +import Label from "./form-label.svelte"; +import Legend from "./form-legend.svelte"; + +const Control = FormPrimitive.Control; + +export { + Button, + Control, + Description, + ElementField, + Field, + FieldErrors, + Fieldset, + Button as FormButton, + Control as FormControl, + Description as FormDescription, + ElementField as FormElementField, + // + Field as FormField, + FieldErrors as FormFieldErrors, + Fieldset as FormFieldset, + Label as FormLabel, + Legend as FormLegend, + Label, + Legend, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/hover-card/hover-card-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/hover-card/hover-card-content.svelte new file mode 100644 index 00000000000000..c8c2f843bf40a2 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/hover-card/hover-card-content.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/hover-card/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/hover-card/index.ts new file mode 100644 index 00000000000000..f4050c4c5b4cd2 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/hover-card/index.ts @@ -0,0 +1,14 @@ +import { LinkPreview as HoverCardPrimitive } from "bits-ui"; + +import Content from "./hover-card-content.svelte"; +const Root = HoverCardPrimitive.Root; +const Trigger = HoverCardPrimitive.Trigger; + +export { + Content, + Root as HoverCard, + Content as HoverCardContent, + Trigger as HoverCardTrigger, + Root, + Trigger, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/input/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/input/index.ts new file mode 100644 index 00000000000000..f0bccb7294a2d6 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/input/index.ts @@ -0,0 +1,30 @@ +import Root from "./input.svelte"; + +export type FormInputEvent = T & { + currentTarget: EventTarget & HTMLInputElement; +}; +export type InputEvents = { + blur: FormInputEvent; + change: FormInputEvent; + click: FormInputEvent; + focus: FormInputEvent; + focusin: FormInputEvent; + focusout: FormInputEvent; + keydown: FormInputEvent; + keypress: FormInputEvent; + keyup: FormInputEvent; + mouseover: FormInputEvent; + mouseenter: FormInputEvent; + mouseleave: FormInputEvent; + mousemove: FormInputEvent; + paste: FormInputEvent; + input: FormInputEvent; + wheel: FormInputEvent; + selectionchange: FormInputEvent; +}; + +export { + // + Root as Input, + Root, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/input/input.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/input/input.svelte new file mode 100644 index 00000000000000..6b571f8c78b124 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/input/input.svelte @@ -0,0 +1,44 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/label/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/label/index.ts new file mode 100644 index 00000000000000..93cddaa04c905f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/label/index.ts @@ -0,0 +1,7 @@ +import Root from "./label.svelte"; + +export { + // + Root as Label, + Root, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/label/label.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/label/label.svelte new file mode 100644 index 00000000000000..fe5c1d26bc9d98 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/label/label.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/index.ts new file mode 100644 index 00000000000000..63b19141eeda9a --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/index.ts @@ -0,0 +1,25 @@ +import Content from "./pagination-content.svelte"; +import Ellipsis from "./pagination-ellipsis.svelte"; +import Item from "./pagination-item.svelte"; +import Link from "./pagination-link.svelte"; +import NextButton from "./pagination-next-button.svelte"; +import PrevButton from "./pagination-prev-button.svelte"; +import Root from "./pagination.svelte"; + +export { + Content, + Ellipsis, + Item, + Link, + NextButton, + // + Root as Pagination, + Content as PaginationContent, + Ellipsis as PaginationEllipsis, + Item as PaginationItem, + Link as PaginationLink, + NextButton as PaginationNextButton, + PrevButton as PaginationPrevButton, + PrevButton, + Root, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-content.svelte new file mode 100644 index 00000000000000..730f7e3af7b976 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-content.svelte @@ -0,0 +1,13 @@ + + +
    + +
diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-ellipsis.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-ellipsis.svelte new file mode 100644 index 00000000000000..0a4b44aa70ce32 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-ellipsis.svelte @@ -0,0 +1,19 @@ + + + + + More pages + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-item.svelte new file mode 100644 index 00000000000000..c812e8f4172e48 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-item.svelte @@ -0,0 +1,13 @@ + + +
  • + +
  • diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-link.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-link.svelte new file mode 100644 index 00000000000000..641f9f48217d01 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-link.svelte @@ -0,0 +1,34 @@ + + + + {page.value} + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-next-button.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-next-button.svelte new file mode 100644 index 00000000000000..c28dc84c8e8463 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-next-button.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-prev-button.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-prev-button.svelte new file mode 100644 index 00000000000000..f7d6a36594077b --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination-prev-button.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination.svelte new file mode 100644 index 00000000000000..2c740342275291 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/pagination/pagination.svelte @@ -0,0 +1,33 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/popover/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/popover/index.ts new file mode 100644 index 00000000000000..67f21374ba03d6 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/popover/index.ts @@ -0,0 +1,18 @@ +import { Popover as PopoverPrimitive } from "bits-ui"; +import Content from "./popover-content.svelte"; + +const Root = PopoverPrimitive.Root; +const Trigger = PopoverPrimitive.Trigger; +const Close = PopoverPrimitive.Close; + +export { + Close, + Content, + // + Root as Popover, + Close as PopoverClose, + Content as PopoverContent, + Trigger as PopoverTrigger, + Root, + Trigger, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/popover/popover-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/popover/popover-content.svelte new file mode 100644 index 00000000000000..6934db978f01eb --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/popover/popover-content.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/progress/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/progress/index.ts new file mode 100644 index 00000000000000..d90fd9b9312a50 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/progress/index.ts @@ -0,0 +1,7 @@ +import Root from "./progress.svelte"; + +export { + // + Root as Progress, + Root, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/progress/progress.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/progress/progress.svelte new file mode 100644 index 00000000000000..1424df401d2617 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/progress/progress.svelte @@ -0,0 +1,21 @@ + + + +
    +
    diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/index.ts new file mode 100644 index 00000000000000..39207f246aaaff --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/index.ts @@ -0,0 +1,15 @@ +import { RadioGroup as RadioGroupPrimitive } from "bits-ui"; + +import Item from "./radio-group-item.svelte"; +import Root from "./radio-group.svelte"; +const Input = RadioGroupPrimitive.Input; + +export { + Input, + Item, + // + Root as RadioGroup, + Input as RadioGroupInput, + Item as RadioGroupItem, + Root, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/radio-group-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/radio-group-item.svelte new file mode 100644 index 00000000000000..350dd3c6c4011e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/radio-group-item.svelte @@ -0,0 +1,28 @@ + + + +
    + + + +
    +
    diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/radio-group.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/radio-group.svelte new file mode 100644 index 00000000000000..f4ec34671919dd --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/radio-group/radio-group.svelte @@ -0,0 +1,14 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/select/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/index.ts new file mode 100644 index 00000000000000..2531700871372e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/index.ts @@ -0,0 +1,33 @@ +import { Select as SelectPrimitive } from "bits-ui"; +import Content from "./select-content.svelte"; +import Item from "./select-item.svelte"; +import Label from "./select-label.svelte"; +import Separator from "./select-separator.svelte"; +import Trigger from "./select-trigger.svelte"; + +const Root = SelectPrimitive.Root; +const Group = SelectPrimitive.Group; +const Input = SelectPrimitive.Input; +const Value = SelectPrimitive.Value; + +export { + Content, + Group, + Input, + Item, + Label, + Root, + // + Root as Select, + Content as SelectContent, + Group as SelectGroup, + Input as SelectInput, + Item as SelectItem, + Label as SelectLabel, + Separator as SelectSeparator, + Trigger as SelectTrigger, + Value as SelectValue, + Separator, + Trigger, + Value, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-content.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-content.svelte new file mode 100644 index 00000000000000..cf5d76d0cfd924 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-content.svelte @@ -0,0 +1,39 @@ + + + +
    + +
    +
    diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-item.svelte new file mode 100644 index 00000000000000..922286e21f075b --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-item.svelte @@ -0,0 +1,40 @@ + + + + + + + + + + {label || value} + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-label.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-label.svelte new file mode 100644 index 00000000000000..17432017b366f4 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-label.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-separator.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-separator.svelte new file mode 100644 index 00000000000000..49a211e97f5d19 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-separator.svelte @@ -0,0 +1,11 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-trigger.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-trigger.svelte new file mode 100644 index 00000000000000..f275970c88dab1 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/select/select-trigger.svelte @@ -0,0 +1,27 @@ + + +span]:line-clamp-1', + className + )} + {...$$restProps} + let:builder + on:click + on:keydown +> + +
    + +
    +
    diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/separator/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/separator/index.ts new file mode 100644 index 00000000000000..d66644e4b3e693 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from "./separator.svelte"; + +export { + Root, + // + Root as Separator, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/separator/separator.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/separator/separator.svelte new file mode 100644 index 00000000000000..499bf675a6f3d8 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/separator/separator.svelte @@ -0,0 +1,22 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/skeleton/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/skeleton/index.ts new file mode 100644 index 00000000000000..cb26b2c6de00e7 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/skeleton/index.ts @@ -0,0 +1,7 @@ +import Root from "./skeleton.svelte"; + +export { + Root, + // + Root as Skeleton, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/skeleton/skeleton.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/skeleton/skeleton.svelte new file mode 100644 index 00000000000000..9d9ad7b0899db2 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/skeleton/skeleton.svelte @@ -0,0 +1,11 @@ + + +
    diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/sonner/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/sonner/index.ts new file mode 100644 index 00000000000000..1ad9f4a2ab5b7e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/sonner/index.ts @@ -0,0 +1 @@ +export { default as Toaster } from "./sonner.svelte"; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/sonner/sonner.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/sonner/sonner.svelte new file mode 100644 index 00000000000000..bc639e9061a70c --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/sonner/sonner.svelte @@ -0,0 +1,19 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/switch/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/switch/index.ts new file mode 100644 index 00000000000000..99620eb8719818 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/switch/index.ts @@ -0,0 +1,7 @@ +import Root from "./switch.svelte"; + +export { + Root, + // + Root as Switch, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/switch/switch.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/switch/switch.svelte new file mode 100644 index 00000000000000..ae1be09c47cadf --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/switch/switch.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/textarea/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/textarea/index.ts new file mode 100644 index 00000000000000..8f1549381cc05e --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/textarea/index.ts @@ -0,0 +1,28 @@ +import Root from "./textarea.svelte"; + +type FormTextareaEvent = T & { + currentTarget: EventTarget & HTMLTextAreaElement; +}; + +type TextareaEvents = { + blur: FormTextareaEvent; + change: FormTextareaEvent; + click: FormTextareaEvent; + focus: FormTextareaEvent; + keydown: FormTextareaEvent; + keypress: FormTextareaEvent; + keyup: FormTextareaEvent; + mouseover: FormTextareaEvent; + mouseenter: FormTextareaEvent; + mouseleave: FormTextareaEvent; + paste: FormTextareaEvent; + input: FormTextareaEvent; +}; + +export { + Root, + // + Root as Textarea, + type FormTextareaEvent, + type TextareaEvents, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/textarea/textarea.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/textarea/textarea.svelte new file mode 100644 index 00000000000000..85b4194e4e7e23 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/textarea/textarea.svelte @@ -0,0 +1,38 @@ + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/index.ts new file mode 100644 index 00000000000000..baa205da401f37 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/index.ts @@ -0,0 +1,23 @@ +import type { toggleVariants } from "$lib/components/ui/toggle/index"; +import { getContext, setContext } from "svelte"; +import type { VariantProps } from "tailwind-variants"; +import Item from "./toggle-group-item.svelte"; +import Root from "./toggle-group.svelte"; + +export type ToggleVariants = VariantProps; + +export function setToggleGroupCtx(props: ToggleVariants) { + setContext("toggleGroup", props); +} + +export function getToggleGroupCtx() { + return getContext("toggleGroup"); +} + +export { + Item, + Root, + // + Root as ToggleGroup, + Item as ToggleGroupItem, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/toggle-group-item.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/toggle-group-item.svelte new file mode 100644 index 00000000000000..150f27fb7483bc --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/toggle-group-item.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/toggle-group.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/toggle-group.svelte new file mode 100644 index 00000000000000..3aa9bc6635ea6c --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle-group/toggle-group.svelte @@ -0,0 +1,30 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle/index.ts b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle/index.ts new file mode 100644 index 00000000000000..7cd4dd4d3b4edb --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle/index.ts @@ -0,0 +1,31 @@ +import { tv, type VariantProps } from "tailwind-variants"; +import Root from "./toggle.svelte"; + +export const toggleVariants = tv({ + base: "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground", + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + }, + size: { + default: "h-10 px-3", + sm: "h-9 px-2.5", + lg: "h-11 px-5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +export type Variant = VariantProps["variant"]; +export type Size = VariantProps["size"]; + +export { + Root, + // + Root as Toggle, +}; diff --git a/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle/toggle.svelte b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle/toggle.svelte new file mode 100644 index 00000000000000..a2786bd02afb35 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/components/ui/toggle/toggle.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/test/integration/vite-build/the-test-app/app/lib/schemas.ts b/test/integration/vite-build/the-test-app/app/lib/schemas.ts new file mode 100644 index 00000000000000..c897f34a54972c --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/schemas.ts @@ -0,0 +1,163 @@ +import { z } from 'zod'; + +const usernameSchema = z + .string() + .trim() + .min(4, 'Username cannot contain at least 4 characters') + .max(32, 'Username cannot contain more than 32 characters') + .regex(/^[a-z0+-9_-]+$/, 'Username must be lowercase and can contain only letters and numbers'); +const passwordSchema = z + .string() + .min(4, 'Password must contain at least 4 characters') + .max(255, 'Password cannot contain more than 255 characters'); + +export const loginSchema = z.object({ + username: usernameSchema, + password: passwordSchema, +}); + +export type LoginSchema = typeof loginSchema; + +export const registerSchema = z + .object({ + username: usernameSchema, + password: passwordSchema, + confirmPassword: passwordSchema, + email: z.string().email().optional(), + }) + .superRefine(({ confirmPassword, password }, ctx) => { + if (confirmPassword !== password) { + ctx.addIssue({ + code: 'custom', + message: "The passwords don't match", + path: ['confirmPassword'], + }); + } + }); + +export type RegisterSchema = typeof registerSchema; + +export const recoverSchema = z.object({ + username: usernameSchema, +}); + +export type RecoverSchema = typeof recoverSchema; + +export const resetSchema = z + .object({ + code: z.string().length(32, 'Invalid recovery code'), + password: passwordSchema, + confirmPassword: passwordSchema, + }) + .superRefine(({ confirmPassword, password }, ctx) => { + if (confirmPassword !== password) { + ctx.addIssue({ + code: 'custom', + message: "The passwords don't match", + path: ['confirmPassword'], + }); + } + }); + +export type ResetSchema = typeof resetSchema; + +export const editArchiveSchema = z + .object({ + title: z.string().min(1, 'Title is required'), + slug: z.string(), + description: z.string().optional(), + pages: z.number().min(1), + thumbnail: z.number().min(1), + language: z.string().optional(), + releasedAt: z.string().optional(), + hasMetadata: z.boolean(), + sources: z.array( + z.object({ + name: z.string().min(1, "Source name can't be empty"), + url: z.string().url('The given URL is not valid').optional().or(z.literal('')), + }) + ), + protected: z.boolean(), + }) + .superRefine(({ pages, thumbnail }, ctx) => { + if (thumbnail > pages) { + ctx.addIssue({ + code: 'custom', + message: "The thumbnail can't be bigger than the number of pages", + path: ['thumbnail'], + }); + } + }); + +export type EditArchiveSchema = typeof editArchiveSchema; + +export const editTagsSchema = z.object({ + tags: z.array(z.object({ namespace: z.string(), name: z.string() })), +}); + +export type EditTagsSchema = typeof editTagsSchema; + +export const sortSchema = z.enum([ + 'released_at', + 'created_at', + 'updated_at', + 'title', + 'pages', + 'random', + 'saved_at', + 'collection_order', + 'series_order', +]); + +export type Sort = z.infer; + +export const orderSchema = z.enum(['asc', 'desc']); + +export type Order = z.infer; + +export const createCollectionSchema = z.object({ + name: z + .string() + .min(1, `Collection name can't be empty`) + .max(500, `Collection name should be 500 less than characters`), + archives: z.array(z.number()).default([]), +}); + +export const userEditSchema = z + .object({ + username: z.string(), + email: z.union([z.literal('').optional(), z.string().email()]), + currentPassword: z.string().optional(), + newPassword: z.union([z.literal('').optional(), passwordSchema]), + confirmNewPassword: z.union([z.literal('').optional(), passwordSchema]), + }) + .superRefine(({ currentPassword, confirmNewPassword, newPassword }, ctx) => { + if (currentPassword?.length && newPassword?.length && currentPassword === newPassword) { + ctx.addIssue({ + code: 'custom', + message: 'The new password is the same as the current one', + path: ['newPassword'], + }); + + return; + } + + if (confirmNewPassword !== newPassword) { + ctx.addIssue({ + code: 'custom', + message: "The new passwords don't match", + path: ['confirmNewPassword'], + }); + } + }); + +export const userDeleteSchema = z.object({ + currentPassword: z.string(), +}); + +export const createSeriesSchema = z.object({ + title: z.string().min(1, { message: 'A title for the series is required' }).max(1000), + chapters: z.array(z.number()), +}); + +export type CreateSeriesSchema = typeof createSeriesSchema; diff --git a/test/integration/vite-build/the-test-app/app/lib/stores.ts b/test/integration/vite-build/the-test-app/app/lib/stores.ts new file mode 100644 index 00000000000000..8f929cf1d47d63 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/stores.ts @@ -0,0 +1,3 @@ +import { writable } from "svelte/store"; + +export const query = writable(""); diff --git a/test/integration/vite-build/the-test-app/app/lib/utils.ts b/test/integration/vite-build/the-test-app/app/lib/utils.ts new file mode 100644 index 00000000000000..623c87ef7d54e8 --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/lib/utils.ts @@ -0,0 +1,75 @@ +import { clsx, type ClassValue } from "clsx"; +import dayjs from "dayjs"; +import isToday from "dayjs/plugin/isToday"; +import isYesterday from "dayjs/plugin/isYesterday"; +import localizedFormat from "dayjs/plugin/localizedFormat"; +import relativeTime from "dayjs/plugin/relativeTime"; +import _slugify from "slugify"; +import { cubicOut } from "svelte/easing"; +import type { TransitionConfig } from "svelte/transition"; +import { twMerge } from "tailwind-merge"; + +_slugify.extend({ ".": "-", _: "-", "+": "-" }); + +dayjs.extend(localizedFormat); +dayjs.extend(relativeTime); +dayjs.extend(isToday); +dayjs.extend(isYesterday); + +export const cn = (...inputs: ClassValue[]) => { + return twMerge(clsx(inputs)); +}; + +type FlyAndScaleParams = { + y?: number; + x?: number; + start?: number; + duration?: number; +}; + +export const flyAndScale = ( + node: Element, + params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }, +): TransitionConfig => { + const style = getComputedStyle(node); + const transform = style.transform === "none" ? "" : style.transform; + + const scaleConversion = ( + valueA: number, + scaleA: [number, number], + scaleB: [number, number], + ) => { + const [minA, maxA] = scaleA; + const [minB, maxB] = scaleB; + + const percentage = (valueA - minA) / (maxA - minA); + const valueB = percentage * (maxB - minB) + minB; + + return valueB; + }; + + const styleToString = ( + style: Record, + ): string => { + return Object.keys(style).reduce((str, key) => { + if (style[key] === undefined) return str; + return str + `${key}:${style[key]};`; + }, ""); + }; + + return { + duration: params.duration ?? 200, + delay: 0, + css: (t) => { + const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]); + const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]); + const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]); + + return styleToString({ + transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`, + opacity: t, + }); + }, + easing: cubicOut, + }; +}; diff --git a/test/integration/vite-build/the-test-app/app/routes/+layout.svelte b/test/integration/vite-build/the-test-app/app/routes/+layout.svelte new file mode 100644 index 00000000000000..2c2448009e345d --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/routes/+layout.svelte @@ -0,0 +1,457 @@ + + +
    + + + + +
    + (popoverOpen = open)} + open={shouldAutocomplete && !!filteredTags.length && popoverOpen} + openFocus={inputEl} + portal={formEl} + > +
    (popoverOpen = false)} + > + + (isFocused = false)} + on:focus={() => { + isFocused = true; + popoverOpen = true; + }} + on:input={() => { + popoverOpen = true; + setTimeout(() => { + selectPosition = inputEl.selectionStart ?? -1; + }, 1); + }} + on:keydown={(ev) => { + switch (ev.key) { + case "Escape": + ev.preventDefault(); + break; + case "ArrowDown": + ev.preventDefault(); + if (highligtedIndex >= filteredTags.length) { + highligtedIndex = -1; + } + + highligtedIndex += 1; + break; + case "ArrowUp": + ev.preventDefault(); + + if (highligtedIndex <= -1) { + highligtedIndex = filteredTags.length; + } + + highligtedIndex -= 1; + break; + case "Enter": + if (highligtedIndex >= 0) { + ev.preventDefault(); + } + + insertTag(ev.currentTarget); + + break; + case "Tab": + if (filteredTags.length) { + ev.preventDefault(); + highligtedIndex = 0; + insertTag(ev.currentTarget); + } + + break; + } + }} + on:selectionchange={() => { + setTimeout(() => { + selectPosition = inputEl.selectionStart ?? -1; + }, 1); + }} + type="search" + /> + + {#if sort} + + {/if} + + {#if order} + + {/if} + + {#if seed} + + {/if} + + + + + + {#each filteredTags as tag, i} + {@const value = + `${negate ? "-" : ""}${or ? "~" : ""}${tag.namespace}:${tag.name.split(" ").length > 1 ? `"${tag.name}"` : tag.name}`.toLowerCase()} + + + {/each} + +
    +
    + + + + + + + + + Preferences + + + + + + + Favorites + + + + + Collections + + + + + Read history + + + + + + + Account + + + + + Logout + + + + + + Login + + + + + +
    + +
    + +
    + + + + {#if userFormState === "register"} + (userFormState = state)} + on:result={({ detail }) => handleUserFormResult(detail)} + /> + {:else if userFormState === "recover"} + (userFormState = state)} + on:result={({ detail }) => handleUserFormResult(detail)} + /> + {:else if userFormState === "reset"} + (userFormState = state)} + on:result={({ detail }) => handleUserFormResult(detail)} + /> + {:else if userFormState === "login"} + (userFormState = state)} + on:result={({ detail }) => handleUserFormResult(detail)} + /> + {/if} + + diff --git a/test/integration/vite-build/the-test-app/app/routes/+page.svelte b/test/integration/vite-build/the-test-app/app/routes/+page.svelte new file mode 100644 index 00000000000000..0b0207f34ebb1f --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/routes/+page.svelte @@ -0,0 +1,279 @@ + + +
    + + + + + + + + + + + + + + + + +

    Hello world

    + + + + +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + + + + + + + + + + +
    + + +
    + + + + + No results found. + + + + Search Emoji + + + + Calculator + + + + + + + Profile + ⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + +
    + + + + + + + My Account + + + + + Profile + ⇧⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + Keyboard shortcuts + ⌘K + + + + + + + Team + + + + + Invite users + + + + + Email + + + + Message + + + + More... + + + + + + New Team + ⌘+T + + + + + + GitHub + + + + Support + + + + API + + + + + Log out + ⇧⌘Q + + + + + + + @sveltejs + + +
    +
    +

    @sveltejs

    +

    Cybernetically enhanced web apps.

    +
    + + + Joined September 2022 + +
    +
    +
    +
    +
    + + + + + + + + + + + + {#each pages as page (page.key)} + {#if page.type === "ellipsis"} + + + + {:else} + + + {page.value} + + + {/if} + {/each} + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/app/routes/sub/+page.svelte b/test/integration/vite-build/the-test-app/app/routes/sub/+page.svelte new file mode 100644 index 00000000000000..9095830ea1879c --- /dev/null +++ b/test/integration/vite-build/the-test-app/app/routes/sub/+page.svelte @@ -0,0 +1,279 @@ + + +
    + + + + + + + + + + + + + + + + +

    Hello world

    + + + + +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + + + + + + + + + + +
    + + +
    + + + + + No results found. + + + + Search Emoji + + + + Calculator + + + + + + + Profile + ⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + +
    + + + + + + + My Account + + + + + Profile + ⇧⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + Keyboard shortcuts + ⌘K + + + + + + + Team + + + + + Invite users + + + + + Email + + + + Message + + + + More... + + + + + + New Team + ⌘+T + + + + + + GitHub + + + + Support + + + + API + + + + + Log out + ⇧⌘Q + + + + + + + @sveltejs + + +
    +
    +

    @sveltejs

    +

    Cybernetically enhanced web apps.

    +
    + + + Joined September 2022 + +
    +
    +
    +
    +
    + + + + + + + + + + + + {#each pages as page (page.key)} + {#if page.type === "ellipsis"} + + + + {:else} + + + {page.value} + + + {/if} + {/each} + + + + + + + + diff --git a/test/integration/vite-build/the-test-app/bun.lock b/test/integration/vite-build/the-test-app/bun.lock new file mode 100644 index 00000000000000..87254e1f306f47 --- /dev/null +++ b/test/integration/vite-build/the-test-app/bun.lock @@ -0,0 +1,1837 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "bun-issue", + "dependencies": { + "@ethercorps/sveltekit-og": "^3.0.0", + "@internationalized/date": "^3.6.0", + "@lucia-auth/adapter-postgresql": "^3.1.2", + "@lucia-auth/adapter-sqlite": "^3.0.2", + "@tailwindcss/container-queries": "^0.1.1", + "@types/cookie": "^0.6.0", + "bits-ui": "^0.21.16", + "camelcase-keys": "^9.1.3", + "capitalize": "^2.0.4", + "chalk": "^5.3.0", + "cli-progress": "^3.12.0", + "clsx": "^2.1.1", + "cmdk-sv": "^0.0.18", + "commander": "^12.1.0", + "confbox": "^0.1.8", + "cookie": "^0.6.0", + "dayjs": "^1.11.13", + "dedent": "^1.5.3", + "dotenv": "^16.4.7", + "fflate": "^0.8.2", + "formsnap": "^1.0.1", + "fuzzball": "^2.1.3", + "kysely": "^0.27.5", + "kysely-bun-sqlite": "^0.3.2", + "lucia": "^3.2.2", + "lucide-svelte": "^0.454.0", + "magic-bytes.js": "^1.10.0", + "natural-compare-lite": "^1.4.0", + "node-addon-api": "^8.3.0", + "node-gyp": "^10.3.1", + "node-html-parser": "^7.0.1", + "node-stream-zip": "^1.15.0", + "nodemailer": "^6.9.16", + "p-map": "^7.0.3", + "p-queue": "^8.0.1", + "pg": "^8.13.1", + "pretty-bytes": "^6.1.1", + "prompts": "^2.4.2", + "ramda": "^0.30.1", + "sharp": "^0.33.5", + "slugify": "^1.6.6", + "streamsaver": "^2.0.6", + "string-pixel-width": "^1.11.0", + "strip-ansi": "^7.1.0", + "svelte-dnd-action": "^0.9.53", + "svelte-meta-tags": "^3.1.4", + "svelte-sonner": "^0.3.28", + "sveltekit-superforms": "^2.22.1", + "tailwind-merge": "^2.5.5", + "tailwind-variants": "^0.2.1", + "tmp": "^0.2.3", + "ts-pattern": "^5.6.0", + "type-fest": "^4.30.2", + "vite": "^5.4.11", + "windows-1252": "^3.0.4", + "xml2js": "^0.6.2", + "yaml": "^2.6.1", + "zod": "^3.24.1", + "zod-urlsearchparams": "^0.0.14", + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^3.3.1", + "@sveltejs/adapter-node": "^5.2.12", + "@sveltejs/kit": "2.11", + "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@types/bun": "^1.1.14", + "@types/capitalize": "^2.0.2", + "@types/cli-progress": "^3.11.6", + "@types/eslint": "^8.56.12", + "@types/natural-compare-lite": "^1.4.2", + "@types/node": "^22.10.2", + "@types/nodemailer": "^6.4.17", + "@types/pg": "^8.11.10", + "@types/prompts": "^2.4.9", + "@types/ramda": "^0.30.2", + "@types/string-pixel-width": "^1.10.3", + "@types/tmp": "^0.2.6", + "@types/xml2js": "^0.4.14", + "autoprefixer": "^10.4.20", + "eslint": "^9.17.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-perfectionist": "^3.9.1", + "eslint-plugin-svelte": "^2.46.1", + "globals": "^15.14.0", + "kysely-codegen": "^0.16.8", + "kysely-ctl": "^0.9.0", + "make-vfs": "^1.0.15", + "p-limit": "^6.1.0", + "postcss": "^8.4.49", + "prettier": "^3.4.2", + "prettier-plugin-organize-imports": "^4.1.0", + "prettier-plugin-svelte": "^3.3.2", + "prettier-plugin-tailwindcss": "^0.6.9", + "svelte": "^4.2.19", + "svelte-check": "^3.8.6", + "tailwindcss": "3.4.17", + "tslib": "^2.8.1", + "typescript": "^5.7.2", + "typescript-eslint": "^8.18.1", + }, + }, + }, + "trustedDependencies": [ + "sharp", + "@sveltejs/kit", + "esbuild", + "svelte-preprocess", + ], + "packages": { + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@ark/schema": ["@ark/schema@0.39.0", "", { "dependencies": { "@ark/util": "0.39.0" } }, "sha512-LQbQUb3Sj461LgklXObAyUJNtsUUCBxZlO2HqRLYvRSqpStm0xTMrXn51DwBNNxeSULvKVpXFwoxiSec9kwKww=="], + + "@ark/util": ["@ark/util@0.39.0", "", {}, "sha512-90APHVklk8BP4kku7hIh1BgrhuyKYqoZ4O7EybtFRo7cDl9mIyc/QUbGvYDg//73s0J2H0I/gW9pzroA1R4IBQ=="], + + "@babel/runtime": ["@babel/runtime@7.26.7", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.23.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.19.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA=="], + + "@eslint/core": ["@eslint/core@0.10.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.2.0", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w=="], + + "@eslint/js": ["@eslint/js@9.19.0", "", {}, "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.5", "", {}, "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.5", "", { "dependencies": { "@eslint/core": "^0.10.0", "levn": "^0.4.1" } }, "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A=="], + + "@ethercorps/svelte-h2j": ["@ethercorps/svelte-h2j@0.1.0", "", { "peerDependencies": { "svelte": "^4.0.0" } }, "sha512-0cs5FgGgiJRgHr2paR3/49Fv/KsOjqbLEPbgZjJtdBiqUD3awZwgoK6ynwTA3zBq+KfHqAJjJU1XWbCwQMih3Q=="], + + "@ethercorps/sveltekit-og": ["@ethercorps/sveltekit-og@3.0.0", "", { "dependencies": { "@ethercorps/svelte-h2j": "^0.1.0", "@resvg/resvg-js": "^2.6.0", "satori": "^0.10.11" }, "peerDependencies": { "svelte": "^4.0.0" } }, "sha512-CQRmcfCPnTEqP+EeHBE7wWp1sNxpBaT4Fb5Js5fGnWEgFFIDbJEEcFiT0Uwc1CteolXY+CyTOg7mokcOtu3d7w=="], + + "@exodus/schemasafe": ["@exodus/schemasafe@1.3.0", "", {}, "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw=="], + + "@floating-ui/core": ["@floating-ui/core@1.6.9", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.6.13", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.9" } }, "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], + + "@gcornut/valibot-json-schema": ["@gcornut/valibot-json-schema@0.31.0", "", { "dependencies": { "valibot": "~0.31.0" }, "optionalDependencies": { "@types/json-schema": ">= 7.0.14", "esbuild": ">= 0.18.20", "esbuild-runner": ">= 2.2.2" }, "bin": { "valibot-json-schema": "bin/index.js" } }, "sha512-3xGptCurm23e7nuPQkdrE5rEs1FeTPHhAUsBuwwqG4/YeZLwJOoYZv+fmsppUEfo5y9lzUwNQrNqLS/q7HMc7g=="], + + "@hapi/hoek": ["@hapi/hoek@9.3.0", "", {}, "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="], + + "@hapi/topo": ["@hapi/topo@5.1.0", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.1", "", {}, "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], + + "@internationalized/date": ["@internationalized/date@3.7.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@lucia-auth/adapter-postgresql": ["@lucia-auth/adapter-postgresql@3.1.2", "", { "dependencies": { "pg": "^8.8.0", "postgres": "^3.3.5" }, "peerDependencies": { "@neondatabase/serverless": "0.7 - 0.9", "lucia": "3.x" }, "optionalPeers": ["@neondatabase/serverless"] }, "sha512-XgScy312JsaiyJZ0OaUHakk01hFBldF1m8abX4Ctk2Dkt7lEVS/u0xZ2Sf6Hlji1wZtEM0uiIWdeMUu79XcXZA=="], + + "@lucia-auth/adapter-sqlite": ["@lucia-auth/adapter-sqlite@3.0.2", "", { "peerDependencies": { "@libsql/client": "^0.3.0", "better-sqlite3": "8.x - 11.x", "lucia": "3.x" }, "optionalPeers": ["@libsql/client", "better-sqlite3"] }, "sha512-UlXpF+2UoFEdm1AsriJii5BOARwqko6SX29rQ8T8Za7rnjj9KLXLaRVQUgBhGmggAyvzCtguJ2+XOZDsfWm6Sw=="], + + "@melt-ui/svelte": ["@melt-ui/svelte@0.76.2", "", { "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", "@internationalized/date": "^3.5.0", "dequal": "^2.0.3", "focus-trap": "^7.5.2", "nanoid": "^5.0.4" }, "peerDependencies": { "svelte": ">=3 <5" } }, "sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA=="], + + "@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=="], + + "@npmcli/agent": ["@npmcli/agent@2.2.2", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og=="], + + "@npmcli/fs": ["@npmcli/fs@3.1.1", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg=="], + + "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], + + "@oslojs/binary": ["@oslojs/binary@1.0.0", "", {}, "sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ=="], + + "@oslojs/crypto": ["@oslojs/crypto@1.0.1", "", { "dependencies": { "@oslojs/asn1": "1.0.0", "@oslojs/binary": "1.0.0" } }, "sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ=="], + + "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@polka/url": ["@polka/url@1.0.0-next.28", "", {}, "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw=="], + + "@poppinss/macroable": ["@poppinss/macroable@1.0.4", "", {}, "sha512-ct43jurbe7lsUX5eIrj4ijO3j/6zIPp7CDnFWXDs7UPAbw1Pu1iH3oAmFdP4jcskKJBURH5M9oTtyeiUXyHX8Q=="], + + "@resvg/resvg-js": ["@resvg/resvg-js@2.6.2", "", { "optionalDependencies": { "@resvg/resvg-js-android-arm-eabi": "2.6.2", "@resvg/resvg-js-android-arm64": "2.6.2", "@resvg/resvg-js-darwin-arm64": "2.6.2", "@resvg/resvg-js-darwin-x64": "2.6.2", "@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2", "@resvg/resvg-js-linux-arm64-gnu": "2.6.2", "@resvg/resvg-js-linux-arm64-musl": "2.6.2", "@resvg/resvg-js-linux-x64-gnu": "2.6.2", "@resvg/resvg-js-linux-x64-musl": "2.6.2", "@resvg/resvg-js-win32-arm64-msvc": "2.6.2", "@resvg/resvg-js-win32-ia32-msvc": "2.6.2", "@resvg/resvg-js-win32-x64-msvc": "2.6.2" } }, "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q=="], + + "@resvg/resvg-js-android-arm-eabi": ["@resvg/resvg-js-android-arm-eabi@2.6.2", "", { "os": "android", "cpu": "arm" }, "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA=="], + + "@resvg/resvg-js-android-arm64": ["@resvg/resvg-js-android-arm64@2.6.2", "", { "os": "android", "cpu": "arm64" }, "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ=="], + + "@resvg/resvg-js-darwin-arm64": ["@resvg/resvg-js-darwin-arm64@2.6.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A=="], + + "@resvg/resvg-js-darwin-x64": ["@resvg/resvg-js-darwin-x64@2.6.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw=="], + + "@resvg/resvg-js-linux-arm-gnueabihf": ["@resvg/resvg-js-linux-arm-gnueabihf@2.6.2", "", { "os": "linux", "cpu": "arm" }, "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw=="], + + "@resvg/resvg-js-linux-arm64-gnu": ["@resvg/resvg-js-linux-arm64-gnu@2.6.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg=="], + + "@resvg/resvg-js-linux-arm64-musl": ["@resvg/resvg-js-linux-arm64-musl@2.6.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg=="], + + "@resvg/resvg-js-linux-x64-gnu": ["@resvg/resvg-js-linux-x64-gnu@2.6.2", "", { "os": "linux", "cpu": "x64" }, "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw=="], + + "@resvg/resvg-js-linux-x64-musl": ["@resvg/resvg-js-linux-x64-musl@2.6.2", "", { "os": "linux", "cpu": "x64" }, "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ=="], + + "@resvg/resvg-js-win32-arm64-msvc": ["@resvg/resvg-js-win32-arm64-msvc@2.6.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ=="], + + "@resvg/resvg-js-win32-ia32-msvc": ["@resvg/resvg-js-win32-ia32-msvc@2.6.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w=="], + + "@resvg/resvg-js-win32-x64-msvc": ["@resvg/resvg-js-win32-x64-msvc@2.6.2", "", { "os": "win32", "cpu": "x64" }, "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ=="], + + "@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@28.0.2", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw=="], + + "@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="], + + "@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.0", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.32.1", "", { "os": "android", "cpu": "arm" }, "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.32.1", "", { "os": "android", "cpu": "arm64" }, "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.32.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.32.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.32.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.32.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.32.1", "", { "os": "linux", "cpu": "arm" }, "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.32.1", "", { "os": "linux", "cpu": "arm" }, "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.32.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.32.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.32.1", "", { "os": "linux", "cpu": "none" }, "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.32.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.32.1", "", { "os": "linux", "cpu": "none" }, "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.32.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.32.1", "", { "os": "linux", "cpu": "x64" }, "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.32.1", "", { "os": "linux", "cpu": "x64" }, "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.32.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.32.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.32.1", "", { "os": "win32", "cpu": "x64" }, "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q=="], + + "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], + + "@shuding/opentype.js": ["@shuding/opentype.js@1.4.0-beta.0", "", { "dependencies": { "fflate": "^0.7.3", "string.prototype.codepointat": "^0.2.1" }, "bin": { "ot": "bin/ot" } }, "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA=="], + + "@sideway/address": ["@sideway/address@4.1.5", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q=="], + + "@sideway/formula": ["@sideway/formula@3.0.1", "", {}, "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="], + + "@sideway/pinpoint": ["@sideway/pinpoint@2.0.0", "", {}, "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.34.15", "", {}, "sha512-xeIzl3h1Znn9w/LTITqpiwag0gXjA+ldi2ZkXIBxGEppGCW211Tza+eL6D4pKqs10bj5z2umBWk5WL6spQ2OCQ=="], + + "@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@3.3.1", "", { "dependencies": { "import-meta-resolve": "^4.1.0" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-5Sc7WAxYdL6q9j/+D0jJKjGREGlfIevDyHSQ2eNETHcB1TKlQWHcAo8AS8H1QdjNvSXpvOwNjykDUHPEAyGgdQ=="], + + "@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.2.12", "", { "dependencies": { "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ=="], + + "@sveltejs/kit": ["@sveltejs/kit@2.11.1", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.1", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0", "tiny-glob": "^0.2.9" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-dAiHDEd+AOm20eYdMPV1a2eKBOc0s/7XsSs7PCoNv2kKS7BAoVRC9uzR+FQmxLtp8xuEo9z8CtrMQoszkThltQ=="], + + "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@3.1.2", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^2.1.0", "debug": "^4.3.4", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.10", "svelte-hmr": "^0.16.0", "vitefu": "^0.2.5" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.0" } }, "sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA=="], + + "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@2.1.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.0" } }, "sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg=="], + + "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], + + "@tailwindcss/container-queries": ["@tailwindcss/container-queries@0.1.1", "", { "peerDependencies": { "tailwindcss": ">=3.2.0" } }, "sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA=="], + + "@types/bun": ["@types/bun@1.2.1", "", { "dependencies": { "bun-types": "1.2.1" } }, "sha512-iiCeMAKMkft8EPQJxSbpVRD0DKqrh91w40zunNajce3nMNNFd/LnAquVisSZC+UpTMjDwtcdyzbWct08IvEqRA=="], + + "@types/capitalize": ["@types/capitalize@2.0.2", "", {}, "sha512-J3I2HyJL4ui26Nwg6fQHx+1pg4Mn0i25T2Q1DIE1fyfySERXlT7j0F06gI52COlt8J26YETAWUCzrWNH/F/PeA=="], + + "@types/cli-progress": ["@types/cli-progress@3.11.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA=="], + + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], + + "@types/eslint": ["@types/eslint@8.56.12", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g=="], + + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], + + "@types/natural-compare-lite": ["@types/natural-compare-lite@1.4.2", "", {}, "sha512-kk1ie31cI6AUm17qOi72lEOBfpRhcknJPsJQoKBulaZC9y00MHUWqxGTk/luWEnenLB+lHoNThrKAKdYVydlew=="], + + "@types/node": ["@types/node@22.12.0", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA=="], + + "@types/nodemailer": ["@types/nodemailer@6.4.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww=="], + + "@types/pg": ["@types/pg@8.11.11", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^4.0.1" } }, "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw=="], + + "@types/prompts": ["@types/prompts@2.4.9", "", { "dependencies": { "@types/node": "*", "kleur": "^3.0.3" } }, "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA=="], + + "@types/pug": ["@types/pug@2.0.10", "", {}, "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA=="], + + "@types/ramda": ["@types/ramda@0.30.2", "", { "dependencies": { "types-ramda": "^0.30.1" } }, "sha512-PyzHvjCalm2BRYjAU6nIB3TprYwMNOUY/7P/N8bSzp9W/yM2YrtGtAnnVtaCNSeOZ8DzKyFDvaqQs7LnWwwmBA=="], + + "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], + + "@types/string-pixel-width": ["@types/string-pixel-width@1.10.3", "", {}, "sha512-c4F9CgBmKS8KyYg1a8AEHDNOmbOzQDvH76QpuiLksmUxnte7mrNc0mah0W5PFCtXGz+FOtAVLVyqUZxFzN5lpw=="], + + "@types/tmp": ["@types/tmp@0.2.6", "", {}, "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA=="], + + "@types/validator": ["@types/validator@13.12.2", "", {}, "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA=="], + + "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + + "@types/xml2js": ["@types/xml2js@0.4.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ=="], + + "@typeschema/class-validator": ["@typeschema/class-validator@0.3.0", "", { "dependencies": { "@typeschema/core": "0.14.0" }, "peerDependencies": { "class-validator": "^0.14.1" }, "optionalPeers": ["class-validator"] }, "sha512-OJSFeZDIQ8EK1HTljKLT5CItM2wsbgczLN8tMEfz3I1Lmhc5TBfkZ0eikFzUC16tI3d1Nag7um6TfCgp2I2Bww=="], + + "@typeschema/core": ["@typeschema/core@0.14.0", "", { "peerDependencies": { "@types/json-schema": "^7.0.15" }, "optionalPeers": ["@types/json-schema"] }, "sha512-Ia6PtZHcL3KqsAWXjMi5xIyZ7XMH4aSnOQes8mfMLx+wGFGtGRNlwe6Y7cYvX+WfNK67OL0/HSe9t8QDygV0/w=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.22.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.22.0", "@typescript-eslint/type-utils": "8.22.0", "@typescript-eslint/utils": "8.22.0", "@typescript-eslint/visitor-keys": "8.22.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.22.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.22.0", "@typescript-eslint/types": "8.22.0", "@typescript-eslint/typescript-estree": "8.22.0", "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.22.0", "", { "dependencies": { "@typescript-eslint/types": "8.22.0", "@typescript-eslint/visitor-keys": "8.22.0" } }, "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.22.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.22.0", "@typescript-eslint/utils": "8.22.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.22.0", "", {}, "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.22.0", "", { "dependencies": { "@typescript-eslint/types": "8.22.0", "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.8.0" } }, "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.22.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.22.0", "@typescript-eslint/types": "8.22.0", "@typescript-eslint/typescript-estree": "8.22.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.22.0", "", { "dependencies": { "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w=="], + + "@vinejs/compiler": ["@vinejs/compiler@3.0.0", "", {}, "sha512-v9Lsv59nR56+bmy2p0+czjZxsLHwaibJ+SV5iK9JJfehlJMa501jUJQqqz4X/OqKXrxtE3uTQmSqjUqzF3B2mw=="], + + "@vinejs/vine": ["@vinejs/vine@3.0.0", "", { "dependencies": { "@poppinss/macroable": "^1.0.3", "@types/validator": "^13.12.2", "@vinejs/compiler": "^3.0.0", "camelcase": "^8.0.0", "dayjs": "^1.11.13", "dlv": "^1.1.3", "normalize-url": "^8.0.1", "validator": "^13.12.0" } }, "sha512-GeCAHLzKkL2kMFqatgqyiiNh+FILOSAV8x8imBDo6AWQ91w30Kaxw4FnzUDqgcd9z8aCYOBQ7RJxBBGfyr+USQ=="], + + "abbrev": ["abbrev@2.0.0", "", {}, "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ=="], + + "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], + + "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="], + + "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=="], + + "ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + + "arktype": ["arktype@2.0.4", "", { "dependencies": { "@ark/schema": "0.39.0", "@ark/util": "0.39.0" } }, "sha512-S68rWVDnJauwH7/QCm8zCUM3aTe9Xk6oRihdcc3FSUAtxCo/q1Fwq46JhcwB5Ufv1YStwdQRz+00Y/URlvbhAQ=="], + + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], + + "array-includes": ["array-includes@3.1.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ=="], + + "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ=="], + + "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], + + "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], + + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], + + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + + "autoprefixer": ["autoprefixer@10.4.20", "", { "dependencies": { "browserslist": "^4.23.3", "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base64-js": ["base64-js@0.0.8", "", {}, "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "bits-ui": ["bits-ui@0.21.16", "", { "dependencies": { "@internationalized/date": "^3.5.1", "@melt-ui/svelte": "0.76.2", "nanoid": "^5.0.5" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.118" } }, "sha512-XFZ7/bK7j/K+5iktxX/ZpmoFHjYjpPzP5EOO/4bWiaFg5TG1iMcfjDhlBTQnJxD6BoVoHuqeZPHZvaTgF4Iv3Q=="], + + "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.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="], + + "buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "bun-types": ["bun-types@1.2.1", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-p7bmXUWmrPWxhcbFVk7oUXM5jAGt94URaoa3qf4mz43MEhNAo/ot1urzBqctgvuq7y9YxkuN51u+/qm4BiIsHw=="], + + "c12": ["c12@1.11.2", "", { "dependencies": { "chokidar": "^3.6.0", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^1.21.6", "mlly": "^1.7.1", "ohash": "^1.1.3", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.4" }, "optionalPeers": ["magicast"] }, "sha512-oBs8a4uvSDO9dm8b7OCFW7+dgtVrwmwnrVXYzLm43ta7ep2jCn/0MhoUFygIWtxhyy6+/MG7/agvpY0U1Iemew=="], + + "cacache": ["cacache@18.0.4", "", { "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^4.0.0", "ssri": "^10.0.0", "tar": "^6.1.11", "unique-filename": "^3.0.0" } }, "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ=="], + + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g=="], + + "call-bound": ["call-bound@1.0.3", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "get-intrinsic": "^1.2.6" } }, "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], + + "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], + + "camelcase-keys": ["camelcase-keys@9.1.3", "", { "dependencies": { "camelcase": "^8.0.0", "map-obj": "5.0.0", "quick-lru": "^6.1.1", "type-fest": "^4.3.2" } }, "sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg=="], + + "camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001696", "", {}, "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ=="], + + "capitalize": ["capitalize@2.0.4", "", {}, "sha512-wcSyiFqXRYyCoqu0o0ekXzJAKCLMkqWS5QWGlgTJFJKwRmI6pzcN2hBl5VPq9RzLW5Uf4FF/V/lcFfjCtVak2w=="], + + "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + + "class-validator": ["class-validator@0.14.1", "", { "dependencies": { "@types/validator": "^13.11.8", "libphonenumber-js": "^1.10.53", "validator": "^13.9.0" } }, "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ=="], + + "clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="], + + "cli-progress": ["cli-progress@3.12.0", "", { "dependencies": { "string-width": "^4.2.3" } }, "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "cmdk-sv": ["cmdk-sv@0.0.18", "", { "dependencies": { "bits-ui": "^0.21.12", "nanoid": "^5.0.7" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.1" } }, "sha512-istixiQSy9Ez/mQ4VXWB69btqNyDZckbd1XFEwR46Vw+n5zjdmvoWAcOTj0uX3FZXtw9ikwLVmfoW2nwwMClRg=="], + + "code-red": ["code-red@1.0.4", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "@types/estree": "^1.0.1", "acorn": "^8.10.0", "estree-walker": "^3.0.3", "periscopic": "^3.1.0" } }, "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw=="], + + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + + "consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="], + + "cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css-background-parser": ["css-background-parser@0.1.0", "", {}, "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA=="], + + "css-box-shadow": ["css-box-shadow@1.0.0-3", "", {}, "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg=="], + + "css-color-keywords": ["css-color-keywords@1.0.0", "", {}, "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="], + + "css-select": ["css-select@5.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg=="], + + "css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="], + + "css-tree": ["css-tree@2.3.1", "", { "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" } }, "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw=="], + + "css-what": ["css-what@6.1.0", "", {}, "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], + + "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], + + "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], + + "dayjs": ["dayjs@1.11.13", "", {}, "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="], + + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], + + "dedent": ["dedent@1.5.3", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "destr": ["destr@2.0.3", "", {}, "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ=="], + + "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="], + + "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], + + "devalue": ["devalue@5.1.1", "", {}, "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="], + + "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], + + "diff": ["diff@3.5.0", "", {}, "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="], + + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="], + + "dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "effect": ["effect@3.12.7", "", { "dependencies": { "fast-check": "^3.23.1" } }, "sha512-BsDTgSjLbL12g0+vGn5xkOgOVhRSaR3VeHmjcUb0gLvpXACJ9OgmlfeH+/FaAZwM5+omIF3I/j1gC5KJrbK1Aw=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.90", "", {}, "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug=="], + + "emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="], + + "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="], + + "es-abstract": ["es-abstract@1.23.9", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.3", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.0", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-regex": "^1.2.1", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.0", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.18" } }, "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "es-shim-unscopables": ["es-shim-unscopables@1.0.2", "", { "dependencies": { "hasown": "^2.0.0" } }, "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw=="], + + "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], + + "es6-promise": ["es6-promise@3.3.1", "", {}, "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg=="], + + "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "esbuild-runner": ["esbuild-runner@2.2.2", "", { "dependencies": { "source-map-support": "0.5.21", "tslib": "2.4.0" }, "peerDependencies": { "esbuild": "*" }, "bin": { "esr": "bin/esr.js" } }, "sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.19.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA=="], + + "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], + + "eslint-config-prettier": ["eslint-config-prettier@9.1.0", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw=="], + + "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], + + "eslint-module-utils": ["eslint-module-utils@2.12.0", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg=="], + + "eslint-plugin-import": ["eslint-plugin-import@2.31.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A=="], + + "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@3.9.1", "", { "dependencies": { "@typescript-eslint/types": "^8.9.0", "@typescript-eslint/utils": "^8.9.0", "minimatch": "^9.0.5", "natural-compare-lite": "^1.4.0" }, "peerDependencies": { "astro-eslint-parser": "^1.0.2", "eslint": ">=8.0.0", "svelte": ">=3.0.0", "svelte-eslint-parser": "^0.41.1", "vue-eslint-parser": ">=9.0.0" }, "optionalPeers": ["astro-eslint-parser", "svelte", "svelte-eslint-parser", "vue-eslint-parser"] }, "sha512-9WRzf6XaAxF4Oi5t/3TqKP5zUjERhasHmLFHin2Yw6ZAp/EP/EVA2dr3BhQrrHWCm5SzTMZf0FcjDnBkO2xFkA=="], + + "eslint-plugin-svelte": ["eslint-plugin-svelte@2.46.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@jridgewell/sourcemap-codec": "^1.4.15", "eslint-compat-utils": "^0.5.1", "esutils": "^2.0.3", "known-css-properties": "^0.35.0", "postcss": "^8.4.38", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.1.0", "semver": "^7.6.2", "svelte-eslint-parser": "^0.43.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw=="], + + "eslint-scope": ["eslint-scope@8.2.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], + + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], + + "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], + + "exponential-backoff": ["exponential-backoff@3.1.1", "", {}, "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw=="], + + "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "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.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "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=="], + + "fastq": ["fastq@1.18.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw=="], + + "fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="], + + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.2", "", {}, "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA=="], + + "focus-trap": ["focus-trap@7.6.4", "", { "dependencies": { "tabbable": "^6.2.0" } }, "sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw=="], + + "for-each": ["for-each@0.3.4", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw=="], + + "foreground-child": ["foreground-child@3.3.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" } }, "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg=="], + + "formsnap": ["formsnap@1.0.1", "", { "dependencies": { "nanoid": "^5.0.5" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.1", "sveltekit-superforms": "^2.3.0" } }, "sha512-TvU9CoLSiacW1c7wXhLiyVpyy/LBfG0CEFDbs3M3jrsxBSrkTpsuhbQ8JYKY3CNCmIhZlgxCH+Vqr7RBF9G53w=="], + + "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], + + "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], + + "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], + + "fuzzball": ["fuzzball@2.1.3", "", { "dependencies": { "heap": ">=0.2.0", "setimmediate": "^1.0.5", "string.fromcodepoint": "^0.2.1", "string.prototype.codepointat": "^0.2.0" } }, "sha512-HfhHw16GRPq342cye8gtPoL7PIN5a8MEewVK/pybr2tAe7nlptP91aw7PFElVValARSKVJYPY5z5sW72JH20Hw=="], + + "get-intrinsic": ["get-intrinsic@1.2.7", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], + + "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], + + "get-tsconfig": ["get-tsconfig@4.10.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A=="], + + "giget": ["giget@1.2.4", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.5.1", "ohash": "^1.1.4", "pathe": "^2.0.2", "tar": "^6.2.1" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-Wv+daGyispVoA31TrWAVR+aAdP7roubTPEM/8JzRnqXhLbdJH0T9eQyXVFF8fjk3WKTsctII6QcyxILYgNp2DA=="], + + "git-diff": ["git-diff@2.0.6", "", { "dependencies": { "chalk": "^2.3.2", "diff": "^3.5.0", "loglevel": "^1.6.1", "shelljs": "^0.8.1", "shelljs.exec": "^1.1.7" } }, "sha512-/Iu4prUrydE3Pb3lCBMbcSNIf81tgGt0W1ZwknnyF62t3tHmtiJTRj0f+1ZIhp3+Rh0ktz1pJVoa7ZXUCskivA=="], + + "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@15.14.0", "", {}, "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig=="], + + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + + "globalyzer": ["globalyzer@0.1.0", "", {}, "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q=="], + + "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], + + "heap": ["heap@0.2.7", "", {}, "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg=="], + + "hex-rgb": ["hex-rgb@4.3.0", "", {}, "sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw=="], + + "http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="], + + "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.0", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw=="], + + "import-meta-resolve": ["import-meta-resolve@4.1.0", "", {}, "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + + "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.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + + "interpret": ["interpret@1.4.0", "", {}, "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="], + + "ip-address": ["ip-address@9.0.5", "", { "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" } }, "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g=="], + + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], + + "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + + "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], + + "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], + + "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.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], + + "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="], + + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], + + "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], + + "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], + + "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], + + "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], + + "is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], + + "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], + + "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], + + "is-weakref": ["is-weakref@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2" } }, "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q=="], + + "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], + + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + + "isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], + + "joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsbn": ["jsbn@1.1.0", "", {}, "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + + "known-css-properties": ["known-css-properties@0.35.0", "", {}, "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A=="], + + "kysely": ["kysely@0.27.5", "", {}, "sha512-s7hZHcQeSNKpzCkHRm8yA+0JPLjncSWnjb+2TIElwS2JAqYr+Kv3Ess+9KFfJS0C1xcQ1i9NkNHpWwCYpHMWsA=="], + + "kysely-bun-sqlite": ["kysely-bun-sqlite@0.3.2", "", { "dependencies": { "bun-types": "^1.0.25" }, "peerDependencies": { "kysely": "^0.27.2" } }, "sha512-YucMcOGGxNCmlAnkvNfTKZX6Bk1sYsuVVXlQN/5ZUgerlq/J9/EuR3aMOOZ25ASLM7oMglSxfeQxkiw0+hrEOQ=="], + + "kysely-codegen": ["kysely-codegen@0.16.8", "", { "dependencies": { "chalk": "4.1.2", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "git-diff": "^2.0.6", "micromatch": "^4.0.8", "minimist": "^1.2.8", "pluralize": "^8.0.0" }, "peerDependencies": { "@libsql/kysely-libsql": "^0.3.0", "@tediousjs/connection-string": "^0.5.0", "better-sqlite3": ">=7.6.2", "kysely": "^0.27.0", "kysely-bun-sqlite": "^0.3.2", "kysely-bun-worker": "^0.5.3", "mysql2": "^2.3.3 || ^3.0.0", "pg": "^8.8.0", "tarn": "^3.0.0", "tedious": "^18.0.0" }, "optionalPeers": ["@libsql/kysely-libsql", "@tediousjs/connection-string", "better-sqlite3", "kysely-bun-sqlite", "kysely-bun-worker", "mysql2", "pg", "tarn", "tedious"], "bin": { "kysely-codegen": "dist/cli/bin.js" } }, "sha512-+N4SDdI9akUWug0i/3UvlktpfPiCt1mtDQ+pVCqI5E98xcGWpdfVXb4CD7CGGNg+QMXqpiR3bVKd0LgCJQtrPA=="], + + "kysely-ctl": ["kysely-ctl@0.9.0", "", { "dependencies": { "c12": "^1.8.0", "citty": "^0.1.4", "consola": "^3.2.0", "nypm": "^0.3.1", "ofetch": "^1.3.4", "pathe": "^1.1.2", "pkg-types": "^1.1.0", "std-env": "^3.4.0", "tsx": "^4.9.0" }, "peerDependencies": { "kysely": ">=0.18.1 <0.28.0", "kysely-postgres-js": "^2" }, "optionalPeers": ["kysely-postgres-js"], "bin": { "kysely": "dist/bin.js" } }, "sha512-Ek4u/4vXV1nATw/RFXMuG6g76nXcD2f5RSMX/n2lbYDh1sJ53wp7QVYbxuLJwEmfHtLXlQFpDe5xPV2URxs+wg=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "libphonenumber-js": ["libphonenumber-js@1.11.18", "", {}, "sha512-okMm/MCoFrm1vByeVFLBdkFIXLSHy/AIK2AEGgY3eoicfWZeOZqv3GfhtQgICkzs/tqorAMm3a4GBg5qNCrqzg=="], + + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + + "linebreak": ["linebreak@1.1.0", "", { "dependencies": { "base64-js": "0.0.8", "unicode-trie": "^2.0.0" } }, "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash.deburr": ["lodash.deburr@4.1.0", "", {}, "sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "loglevel": ["loglevel@1.9.2", "", {}, "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg=="], + + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "lucia": ["lucia@3.2.2", "", { "dependencies": { "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0" } }, "sha512-P1FlFBGCMPMXu+EGdVD9W4Mjm0DqsusmKgO7Xc33mI5X1bklmsQb0hfzPhXomQr9waWIBDsiOjvr1e6BTaUqpA=="], + + "lucide-svelte": ["lucide-svelte@0.454.0", "", { "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "sha512-TgW17HI7M8LeFZ3NpaDp1LwPGBGMVjx/x81TtK+AacEQvmJcqetqeJNeBT18NMEJP9+zi/Wt+Zc8mo44K5Uszw=="], + + "magic-bytes.js": ["magic-bytes.js@1.10.0", "", {}, "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="], + + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "make-fetch-happen": ["make-fetch-happen@13.0.1", "", { "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", "http-cache-semantics": "^4.1.1", "is-lambda": "^1.0.1", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" } }, "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA=="], + + "make-vfs": ["make-vfs@1.0.15", "", { "bin": { "make-vfs": "dist/cli.js" } }, "sha512-NM1+SMNggHrd8p3YkN0kIgDivIvYWqrXQgPpAv/jgtRLEsOG7pkpPViX3JTEalmv1xsbUHKMBJKjpAdPWHWqmQ=="], + + "map-obj": ["map-obj@5.0.0", "", {}, "sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mdn-data": ["mdn-data@2.0.30", "", {}, "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="], + + "memoize-weak": ["memoize-weak@1.0.2", "", {}, "sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ=="], + + "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.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], + + "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="], + + "minipass-fetch": ["minipass-fetch@3.0.5", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg=="], + + "minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="], + + "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="], + + "minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="], + + "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "mrmime": ["mrmime@2.0.0", "", {}, "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "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=="], + + "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "natural-compare-lite": ["natural-compare-lite@1.4.0", "", {}, "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g=="], + + "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], + + "node-addon-api": ["node-addon-api@8.3.0", "", {}, "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg=="], + + "node-fetch-native": ["node-fetch-native@1.6.6", "", {}, "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="], + + "node-gyp": ["node-gyp@10.3.1", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^10.3.10", "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", "proc-log": "^4.1.0", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^4.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ=="], + + "node-html-parser": ["node-html-parser@7.0.1", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA=="], + + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + + "node-stream-zip": ["node-stream-zip@1.15.0", "", {}, "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw=="], + + "nodemailer": ["nodemailer@6.10.0", "", {}, "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA=="], + + "nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], + + "normalize-url": ["normalize-url@8.0.1", "", {}, "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w=="], + + "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "nypm": ["nypm@0.3.12", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.2.3", "execa": "^8.0.1", "pathe": "^1.1.2", "pkg-types": "^1.2.0", "ufo": "^1.5.4" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + + "object-inspect": ["object-inspect@1.13.3", "", {}, "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA=="], + + "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], + + "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], + + "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], + + "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], + + "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], + + "obuf": ["obuf@1.1.2", "", {}, "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="], + + "ofetch": ["ofetch@1.4.1", "", { "dependencies": { "destr": "^2.0.3", "node-fetch-native": "^1.6.4", "ufo": "^1.5.4" } }, "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw=="], + + "ohash": ["ohash@1.1.4", "", {}, "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], + + "p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "p-map": ["p-map@7.0.3", "", {}, "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA=="], + + "p-queue": ["p-queue@8.1.0", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw=="], + + "p-timeout": ["p-timeout@6.1.4", "", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "pako": ["pako@0.2.9", "", {}, "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-css-color": ["parse-css-color@0.2.1", "", { "dependencies": { "color-name": "^1.1.4", "hex-rgb": "^4.1.0" } }, "sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "periscopic": ["periscopic@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", "is-reference": "^3.0.0" } }, "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw=="], + + "pg": ["pg@8.13.1", "", { "dependencies": { "pg-connection-string": "^2.7.0", "pg-pool": "^3.7.0", "pg-protocol": "^1.7.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, "optionalDependencies": { "pg-cloudflare": "^1.1.1" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ=="], + + "pg-cloudflare": ["pg-cloudflare@1.1.1", "", {}, "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q=="], + + "pg-connection-string": ["pg-connection-string@2.7.0", "", {}, "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA=="], + + "pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="], + + "pg-numeric": ["pg-numeric@1.0.2", "", {}, "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw=="], + + "pg-pool": ["pg-pool@3.7.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g=="], + + "pg-protocol": ["pg-protocol@1.7.0", "", {}, "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ=="], + + "pg-types": ["pg-types@4.0.2", "", { "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", "postgres-array": "~3.0.1", "postgres-bytea": "~3.0.0", "postgres-date": "~2.1.0", "postgres-interval": "^3.0.0", "postgres-range": "^1.1.1" } }, "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng=="], + + "pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], + + "pirates": ["pirates@4.0.6", "", {}, "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg=="], + + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], + + "possible-typed-array-names": ["possible-typed-array-names@1.0.0", "", {}, "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q=="], + + "postcss": ["postcss@8.5.1", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ=="], + + "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], + + "postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="], + + "postcss-load-config": ["postcss-load-config@3.1.4", "", { "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg=="], + + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], + + "postcss-safe-parser": ["postcss-safe-parser@6.0.0", "", { "peerDependencies": { "postcss": "^8.3.3" } }, "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ=="], + + "postcss-scss": ["postcss-scss@4.0.9", "", { "peerDependencies": { "postcss": "^8.4.29" } }, "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "postgres": ["postgres@3.4.5", "", {}, "sha512-cDWgoah1Gez9rN3H4165peY9qfpEo+SA61oQv65O3cRUE1pOEoJWwddwcqKE8XZYjbblOJlYDlLV4h67HrEVDg=="], + + "postgres-array": ["postgres-array@3.0.2", "", {}, "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog=="], + + "postgres-bytea": ["postgres-bytea@3.0.0", "", { "dependencies": { "obuf": "~1.1.2" } }, "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw=="], + + "postgres-date": ["postgres-date@2.1.0", "", {}, "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA=="], + + "postgres-interval": ["postgres-interval@3.0.0", "", {}, "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw=="], + + "postgres-range": ["postgres-range@1.1.4", "", {}, "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.4.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ=="], + + "prettier-plugin-organize-imports": ["prettier-plugin-organize-imports@4.1.0", "", { "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9", "vue-tsc": "^2.1.0" }, "optionalPeers": ["vue-tsc"] }, "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A=="], + + "prettier-plugin-svelte": ["prettier-plugin-svelte@3.3.3", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw=="], + + "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.11", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA=="], + + "pretty-bytes": ["pretty-bytes@6.1.1", "", {}, "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ=="], + + "proc-log": ["proc-log@4.2.0", "", {}, "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA=="], + + "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="], + + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + + "property-expr": ["property-expr@2.0.6", "", {}, "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "quick-lru": ["quick-lru@6.1.2", "", {}, "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ=="], + + "ramda": ["ramda@0.30.1", "", {}, "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw=="], + + "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], + + "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "rechoir": ["rechoir@0.6.2", "", { "dependencies": { "resolve": "^1.1.6" } }, "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw=="], + + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], + + "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], + + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], + + "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], + + "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], + + "rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="], + + "rollup": ["rollup@4.32.1", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.32.1", "@rollup/rollup-android-arm64": "4.32.1", "@rollup/rollup-darwin-arm64": "4.32.1", "@rollup/rollup-darwin-x64": "4.32.1", "@rollup/rollup-freebsd-arm64": "4.32.1", "@rollup/rollup-freebsd-x64": "4.32.1", "@rollup/rollup-linux-arm-gnueabihf": "4.32.1", "@rollup/rollup-linux-arm-musleabihf": "4.32.1", "@rollup/rollup-linux-arm64-gnu": "4.32.1", "@rollup/rollup-linux-arm64-musl": "4.32.1", "@rollup/rollup-linux-loongarch64-gnu": "4.32.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.32.1", "@rollup/rollup-linux-riscv64-gnu": "4.32.1", "@rollup/rollup-linux-s390x-gnu": "4.32.1", "@rollup/rollup-linux-x64-gnu": "4.32.1", "@rollup/rollup-linux-x64-musl": "4.32.1", "@rollup/rollup-win32-arm64-msvc": "4.32.1", "@rollup/rollup-win32-ia32-msvc": "4.32.1", "@rollup/rollup-win32-x64-msvc": "4.32.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], + + "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], + + "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], + + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "sander": ["sander@0.5.1", "", { "dependencies": { "es6-promise": "^3.1.2", "graceful-fs": "^4.1.3", "mkdirp": "^0.5.1", "rimraf": "^2.5.2" } }, "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA=="], + + "satori": ["satori@0.10.14", "", { "dependencies": { "@shuding/opentype.js": "1.4.0-beta.0", "css-background-parser": "^0.1.0", "css-box-shadow": "1.0.0-3", "css-to-react-native": "^3.0.0", "emoji-regex": "^10.2.1", "escape-html": "^1.0.3", "linebreak": "^1.1.0", "parse-css-color": "^0.2.1", "postcss-value-parser": "^4.2.0", "yoga-wasm-web": "^0.3.3" } }, "sha512-abovcqmwl97WKioxpkfuMeZmndB1TuDFY/R+FymrZyiGP+pMYomvgSzVPnbNMWHHESOPosVHGL352oFbdAnJcA=="], + + "sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="], + + "schema-dts": ["schema-dts@1.1.2", "", { "peerDependencies": { "typescript": ">=4.1.0" } }, "sha512-MpNwH0dZJHinVxk9bT8XUdjKTxMYrA5bLtrrGmFA6PTLwlOKnhi67XoRd6/ty+Djt6ZC0slR57qFhZDNMI6DhQ=="], + + "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], + + "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], + + "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="], + + "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "shelljs": ["shelljs@0.8.5", "", { "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "bin": { "shjs": "bin/shjs" } }, "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow=="], + + "shelljs.exec": ["shelljs.exec@1.1.8", "", {}, "sha512-vFILCw+lzUtiwBAHV8/Ex8JsFjelFMdhONIsgKNLgTzeRckp2AOYRQtHJE/9LhNvdMmE27AGtzWx0+DHpwIwSw=="], + + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + + "sirv": ["sirv@3.0.0", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "slugify": ["slugify@1.6.6", "", {}, "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="], + + "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], + + "socks": ["socks@2.8.3", "", { "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" } }, "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw=="], + + "socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], + + "sorcery": ["sorcery@0.11.1", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.14", "buffer-crc32": "^1.0.0", "minimist": "^1.2.0", "sander": "^0.5.0" }, "bin": { "sorcery": "bin/sorcery" } }, "sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "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=="], + + "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + + "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], + + "ssri": ["ssri@10.0.6", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ=="], + + "std-env": ["std-env@3.8.0", "", {}, "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w=="], + + "streamsaver": ["streamsaver@2.0.6", "", {}, "sha512-LK4e7TfCV8HzuM0PKXuVUfKyCB1FtT9L0EGxsFk5Up8njj0bXK8pJM9+Wq2Nya7/jslmCQwRK39LFm55h7NBTw=="], + + "string-pixel-width": ["string-pixel-width@1.11.0", "", { "dependencies": { "lodash.deburr": "^4.1.0" } }, "sha512-GeKuNcCza7Gf3tlMJiZY8SF1LtbFGeMUEpHifncgJn+ZcUpnoPyE69HEyb0rXrJ3bejY/M/kBylu7IDlPJD9Ng=="], + + "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-width-cjs": ["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.fromcodepoint": ["string.fromcodepoint@0.2.1", "", {}, "sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg=="], + + "string.prototype.codepointat": ["string.prototype.codepointat@0.2.1", "", {}, "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="], + + "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="], + + "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], + + "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], + + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], + + "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="], + + "superstruct": ["superstruct@2.0.2", "", {}, "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "svelte": ["svelte@4.2.19", "", { "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", "@jridgewell/trace-mapping": "^0.3.18", "@types/estree": "^1.0.1", "acorn": "^8.9.0", "aria-query": "^5.3.0", "axobject-query": "^4.0.0", "code-red": "^1.0.3", "css-tree": "^2.3.1", "estree-walker": "^3.0.3", "is-reference": "^3.0.1", "locate-character": "^3.0.0", "magic-string": "^0.30.4", "periscopic": "^3.1.0" } }, "sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw=="], + + "svelte-check": ["svelte-check@3.8.6", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "chokidar": "^3.4.1", "picocolors": "^1.0.0", "sade": "^1.7.4", "svelte-preprocess": "^5.1.3", "typescript": "^5.0.3" }, "peerDependencies": { "svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-ij0u4Lw/sOTREP13BdWZjiXD/BlHE6/e2e34XzmVmsp5IN4kVa3PWP65NM32JAgwjZlwBg/+JtiNV1MM8khu0Q=="], + + "svelte-dnd-action": ["svelte-dnd-action@0.9.56", "", { "peerDependencies": { "svelte": ">=3.23.0 || ^5.0.0-next.0" } }, "sha512-sp9DyuHiQU8X4VPMQYEiRnQrqnoFXOWOF7HMN9dU1Prbv8sVfU9h+SJ5mjK4nCMj1mejdU9+9cxOBu2NVwgrQw=="], + + "svelte-eslint-parser": ["svelte-eslint-parser@0.43.0", "", { "dependencies": { "eslint-scope": "^7.2.2", "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "postcss": "^8.4.39", "postcss-scss": "^4.0.9" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA=="], + + "svelte-hmr": ["svelte-hmr@0.16.0", "", { "peerDependencies": { "svelte": "^3.19.0 || ^4.0.0" } }, "sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA=="], + + "svelte-meta-tags": ["svelte-meta-tags@3.1.4", "", { "dependencies": { "schema-dts": "^1.1.2" }, "peerDependencies": { "svelte": "^3.55.0 || ^4.0.0" } }, "sha512-TUIfhut0iVeTm7f5v/ZuU/tZ9XsNig9bNN8yK0t2x2WL9qw6AxAVRe9i5XddYJE0SuVwkoDCzjoSg5hXv7oWbQ=="], + + "svelte-preprocess": ["svelte-preprocess@5.1.4", "", { "dependencies": { "@types/pug": "^2.0.6", "detect-indent": "^6.1.0", "magic-string": "^0.30.5", "sorcery": "^0.11.0", "strip-indent": "^3.0.0" }, "peerDependencies": { "@babel/core": "^7.10.2", "coffeescript": "^2.5.1", "less": "^3.11.3 || ^4.0.0", "postcss": "^7 || ^8", "postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "pug": "^3.0.0", "sass": "^1.26.8", "stylus": "^0.55.0", "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", "svelte": "^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0", "typescript": ">=3.9.5 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["@babel/core", "coffeescript", "less", "postcss", "postcss-load-config", "pug", "sass", "stylus", "sugarss", "typescript"] }, "sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA=="], + + "svelte-sonner": ["svelte-sonner@0.3.28", "", { "peerDependencies": { "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0-next.1" } }, "sha512-K3AmlySeFifF/cKgsYNv5uXqMVNln0NBAacOYgmkQStLa/UoU0LhfAACU6Gr+YYC8bOCHdVmFNoKuDbMEsppJg=="], + + "sveltekit-superforms": ["sveltekit-superforms@2.23.1", "", { "dependencies": { "devalue": "^5.1.1", "memoize-weak": "^1.0.2", "ts-deepmerge": "^7.0.2" }, "optionalDependencies": { "@exodus/schemasafe": "^1.3.0", "@gcornut/valibot-json-schema": "^0.31.0", "@sinclair/typebox": "^0.34.14", "@typeschema/class-validator": "^0.3.0", "@vinejs/vine": "^3.0.0", "arktype": "^2.0.0", "class-validator": "^0.14.1", "effect": "^3.12.5", "joi": "^17.13.3", "json-schema-to-ts": "^3.1.1", "superstruct": "^2.0.2", "valibot": "1.0.0-beta.11", "yup": "^1.6.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "@sveltejs/kit": "1.x || 2.x", "svelte": "3.x || 4.x || >=5.0.0-next.51" } }, "sha512-SPj5ac4SMg8SPyP0Zi3ynwXJa7r9U1CTyn+YSyck67zLsjt367Sro4SZnl3yASrLd5kJ6Y57cgIdYJ2aWNArXw=="], + + "tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="], + + "tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], + + "tailwind-variants": ["tailwind-variants@0.2.1", "", { "dependencies": { "tailwind-merge": "^2.2.0" }, "peerDependencies": { "tailwindcss": "*" } }, "sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw=="], + + "tailwindcss": ["tailwindcss@3.4.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.6", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og=="], + + "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + + "tiny-case": ["tiny-case@1.0.3", "", {}, "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="], + + "tiny-glob": ["tiny-glob@0.2.9", "", { "dependencies": { "globalyzer": "0.1.0", "globrex": "^0.1.2" } }, "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg=="], + + "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], + + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + + "tmp": ["tmp@0.2.3", "", {}, "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toposort": ["toposort@2.0.2", "", {}, "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="], + + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], + + "ts-api-utils": ["ts-api-utils@2.0.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ=="], + + "ts-deepmerge": ["ts-deepmerge@7.0.2", "", {}, "sha512-akcpDTPuez4xzULo5NwuoKwYRtjQJ9eoNfBACiBMaXwNAx7B1PKfe5wqUFJuW5uKzQ68YjDFwPaWHDG1KnFGsA=="], + + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + + "ts-pattern": ["ts-pattern@5.6.2", "", {}, "sha512-d4IxJUXROL5NCa3amvMg6VQW2HVtZYmUTPfvVtO7zJWGYLJ+mry9v2OmYm+z67aniQoQ8/yFNadiEwtNS9qQiw=="], + + "ts-toolbelt": ["ts-toolbelt@9.6.0", "", {}, "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w=="], + + "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsx": ["tsx@4.19.2", "", { "dependencies": { "esbuild": "~0.23.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "type-fest": ["type-fest@4.33.0", "", {}, "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g=="], + + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], + + "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], + + "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], + + "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], + + "types-ramda": ["types-ramda@0.30.1", "", { "dependencies": { "ts-toolbelt": "^9.6.0" } }, "sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA=="], + + "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], + + "typescript-eslint": ["typescript-eslint@8.22.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.22.0", "@typescript-eslint/parser": "8.22.0", "@typescript-eslint/utils": "8.22.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw=="], + + "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], + + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "unicode-trie": ["unicode-trie@2.0.0", "", { "dependencies": { "pako": "^0.2.5", "tiny-inflate": "^1.0.0" } }, "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ=="], + + "unique-filename": ["unique-filename@3.0.0", "", { "dependencies": { "unique-slug": "^4.0.0" } }, "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g=="], + + "unique-slug": ["unique-slug@4.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "valibot": ["valibot@1.0.0-beta.11", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Ztl5Iks1Ql7Z6CwkS5oyqguN3G8tmUiNlsHpqbDt6DLMpm+eu+n8Q7f921gI3uHvNZ8xDVkd4cEJP5t+lELOfw=="], + + "validator": ["validator@13.12.0", "", {}, "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg=="], + + "vite": ["vite@5.4.14", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA=="], + + "vitefu": ["vitefu@0.2.5", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["vite"] }, "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q=="], + + "which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], + + "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], + + "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], + + "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], + + "which-typed-array": ["which-typed-array@1.1.18", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.3", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA=="], + + "windows-1252": ["windows-1252@3.0.4", "", {}, "sha512-PxP05UYnSeqhkkcHeT3xhpY/BsMOX6URw4ZW9ljOlhkQ6UZRRj/xvS3o5kG+fwefCztUtW36+DHBBNnWfXPIsw=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], + + "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], + + "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + + "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="], + + "yocto-queue": ["yocto-queue@1.1.1", "", {}, "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g=="], + + "yoga-wasm-web": ["yoga-wasm-web@0.3.3", "", {}, "sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA=="], + + "yup": ["yup@1.6.1", "", { "dependencies": { "property-expr": "^2.0.5", "tiny-case": "^1.0.3", "toposort": "^2.0.2", "type-fest": "^2.19.0" } }, "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA=="], + + "zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], + + "zod-to-json-schema": ["zod-to-json-schema@3.24.1", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w=="], + + "zod-urlsearchparams": ["zod-urlsearchparams@0.0.14", "", { "peerDependencies": { "zod": "^3.0.0" } }, "sha512-3igiTe7g9oZ4AxMJeNqUjvtUk9a8tjeOZwDIWshW4LB0PO98aT9oQ0uiuIeuBz+EZKhRpYJyc/TjWHjylbTx6Q=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "@gcornut/valibot-json-schema/esbuild": ["esbuild@0.23.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.23.1", "@esbuild/android-arm": "0.23.1", "@esbuild/android-arm64": "0.23.1", "@esbuild/android-x64": "0.23.1", "@esbuild/darwin-arm64": "0.23.1", "@esbuild/darwin-x64": "0.23.1", "@esbuild/freebsd-arm64": "0.23.1", "@esbuild/freebsd-x64": "0.23.1", "@esbuild/linux-arm": "0.23.1", "@esbuild/linux-arm64": "0.23.1", "@esbuild/linux-ia32": "0.23.1", "@esbuild/linux-loong64": "0.23.1", "@esbuild/linux-mips64el": "0.23.1", "@esbuild/linux-ppc64": "0.23.1", "@esbuild/linux-riscv64": "0.23.1", "@esbuild/linux-s390x": "0.23.1", "@esbuild/linux-x64": "0.23.1", "@esbuild/netbsd-x64": "0.23.1", "@esbuild/openbsd-arm64": "0.23.1", "@esbuild/openbsd-x64": "0.23.1", "@esbuild/sunos-x64": "0.23.1", "@esbuild/win32-arm64": "0.23.1", "@esbuild/win32-ia32": "0.23.1", "@esbuild/win32-x64": "0.23.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg=="], + + "@gcornut/valibot-json-schema/valibot": ["valibot@0.31.1", "", {}, "sha512-2YYIhPrnVSz/gfT2/iXVTrSj92HwchCt9Cga/6hX4B26iCz9zkIsGTS0HjDYTZfTi1Un0X6aRvhBi1cfqs/i0Q=="], + + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@melt-ui/svelte/nanoid": ["nanoid@5.0.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q=="], + + "@npmcli/fs/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + + "@rollup/plugin-commonjs/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], + + "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "@shuding/opentype.js/fflate": ["fflate@0.7.4", "", {}, "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw=="], + + "@types/prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/typescript-estree/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "bits-ui/nanoid": ["nanoid@5.0.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q=="], + + "cacache/fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="], + + "cacache/p-map": ["p-map@4.0.0", "", { "dependencies": { "aggregate-error": "^3.0.0" } }, "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ=="], + + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "cmdk-sv/nanoid": ["nanoid@5.0.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q=="], + + "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "esbuild-runner/tslib": ["tslib@2.4.0", "", {}, "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="], + + "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "eslint-compat-utils/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + + "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-plugin-perfectionist/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "eslint-plugin-svelte/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "formsnap/nanoid": ["nanoid@5.0.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q=="], + + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "giget/nypm": ["nypm@0.5.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.2", "pkg-types": "^1.3.1", "tinyexec": "^0.3.2", "ufo": "^1.5.4" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-AHzvnyUJYSrrphPhRWWZNcoZfArGNp3Vrc4pm/ZurO74tYNTgAPrEyBQEKy+qioqmWlPXwvMZCG2wOaHlPG0Pw=="], + + "giget/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], + + "git-diff/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=="], + + "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "kysely-codegen/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "mlly/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], + + "node-gyp/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "p-locate/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="], + + "pkg-types/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], + + "postcss-load-config/lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="], + + "postcss-load-config/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "rimraf/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=="], + + "sander/mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], + + "sharp/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + + "shelljs/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=="], + + "string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], + + "svelte-eslint-parser/eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], + + "svelte-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "svelte-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], + + "tailwindcss/postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="], + + "tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "tsx/esbuild": ["esbuild@0.23.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.23.1", "@esbuild/android-arm": "0.23.1", "@esbuild/android-arm64": "0.23.1", "@esbuild/android-x64": "0.23.1", "@esbuild/darwin-arm64": "0.23.1", "@esbuild/darwin-x64": "0.23.1", "@esbuild/freebsd-arm64": "0.23.1", "@esbuild/freebsd-x64": "0.23.1", "@esbuild/linux-arm": "0.23.1", "@esbuild/linux-arm64": "0.23.1", "@esbuild/linux-ia32": "0.23.1", "@esbuild/linux-loong64": "0.23.1", "@esbuild/linux-mips64el": "0.23.1", "@esbuild/linux-ppc64": "0.23.1", "@esbuild/linux-riscv64": "0.23.1", "@esbuild/linux-s390x": "0.23.1", "@esbuild/linux-x64": "0.23.1", "@esbuild/netbsd-x64": "0.23.1", "@esbuild/openbsd-arm64": "0.23.1", "@esbuild/openbsd-x64": "0.23.1", "@esbuild/sunos-x64": "0.23.1", "@esbuild/win32-arm64": "0.23.1", "@esbuild/win32-ia32": "0.23.1", "@esbuild/win32-x64": "0.23.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "wrap-ansi/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "yup/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.23.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.23.1", "", { "os": "android", "cpu": "arm" }, "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.23.1", "", { "os": "android", "cpu": "arm64" }, "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.23.1", "", { "os": "android", "cpu": "x64" }, "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.23.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.23.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.23.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.23.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.23.1", "", { "os": "linux", "cpu": "arm" }, "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.23.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.23.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.23.1", "", { "os": "linux", "cpu": "none" }, "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.23.1", "", { "os": "linux", "cpu": "none" }, "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.23.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.23.1", "", { "os": "linux", "cpu": "none" }, "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.23.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.23.1", "", { "os": "linux", "cpu": "x64" }, "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.23.1", "", { "os": "none", "cpu": "x64" }, "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.23.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.23.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.23.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.23.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ=="], + + "@gcornut/valibot-json-schema/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.23.1", "", { "os": "win32", "cpu": "x64" }, "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg=="], + + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "eslint-plugin-perfectionist/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "git-diff/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], + + "git-diff/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "git-diff/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], + + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "p-locate/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="], + + "pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="], + + "pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="], + + "pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.23.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ=="], + + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.23.1", "", { "os": "android", "cpu": "arm" }, "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ=="], + + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.23.1", "", { "os": "android", "cpu": "arm64" }, "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw=="], + + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.23.1", "", { "os": "android", "cpu": "x64" }, "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg=="], + + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.23.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q=="], + + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.23.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw=="], + + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.23.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA=="], + + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.23.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g=="], + + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.23.1", "", { "os": "linux", "cpu": "arm" }, "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ=="], + + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.23.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g=="], + + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.23.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ=="], + + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.23.1", "", { "os": "linux", "cpu": "none" }, "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw=="], + + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.23.1", "", { "os": "linux", "cpu": "none" }, "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q=="], + + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.23.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw=="], + + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.23.1", "", { "os": "linux", "cpu": "none" }, "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA=="], + + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.23.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw=="], + + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.23.1", "", { "os": "linux", "cpu": "x64" }, "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ=="], + + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.23.1", "", { "os": "none", "cpu": "x64" }, "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA=="], + + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.23.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA=="], + + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.23.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA=="], + + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.23.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A=="], + + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.23.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ=="], + + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.23.1", "", { "os": "win32", "cpu": "x64" }, "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "git-diff/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + + "git-diff/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + + "git-diff/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + } +} diff --git a/test/integration/vite-build/the-test-app/components.json b/test/integration/vite-build/the-test-app/components.json new file mode 100644 index 00000000000000..7dd9959330c0ec --- /dev/null +++ b/test/integration/vite-build/the-test-app/components.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "style": "default", + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/app.css", + "baseColor": "slate" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils" + }, + "typescript": true +} diff --git a/test/integration/vite-build/the-test-app/package.json b/test/integration/vite-build/the-test-app/package.json new file mode 100644 index 00000000000000..1e427d38e0af36 --- /dev/null +++ b/test/integration/vite-build/the-test-app/package.json @@ -0,0 +1,127 @@ +{ + "name": "bun-issue", + "version": "0.0.1", + "private": true, + "scripts": { + "prepare": "svelte-kit sync", + "dev": "bunx --bun vite dev", + "build": "bunx --bun vite build", + "preview": "bunx --bun vite preview", + "start": "bun ./serve.ts", + "cluster": "bun ./cluster.ts", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write ." + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^3.3.1", + "@sveltejs/adapter-node": "^5.2.12", + "@sveltejs/kit": "2.11", + "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@types/bun": "^1.1.14", + "@types/capitalize": "^2.0.2", + "@types/cli-progress": "^3.11.6", + "@types/eslint": "^8.56.12", + "@types/natural-compare-lite": "^1.4.2", + "@types/node": "^22.10.2", + "@types/nodemailer": "^6.4.17", + "@types/pg": "^8.11.10", + "@types/prompts": "^2.4.9", + "@types/ramda": "^0.30.2", + "@types/string-pixel-width": "^1.10.3", + "@types/tmp": "^0.2.6", + "@types/xml2js": "^0.4.14", + "autoprefixer": "^10.4.20", + "eslint": "^9.17.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-perfectionist": "^3.9.1", + "eslint-plugin-svelte": "^2.46.1", + "globals": "^15.14.0", + "kysely-codegen": "^0.16.8", + "kysely-ctl": "^0.9.0", + "make-vfs": "^1.0.15", + "p-limit": "^6.1.0", + "postcss": "^8.4.49", + "prettier": "^3.4.2", + "prettier-plugin-organize-imports": "^4.1.0", + "prettier-plugin-svelte": "^3.3.2", + "prettier-plugin-tailwindcss": "^0.6.9", + "svelte": "^4.2.19", + "svelte-check": "^3.8.6", + "tailwindcss": "3.4.17", + "tslib": "^2.8.1", + "typescript": "^5.7.2", + "typescript-eslint": "^8.18.1" + }, + "type": "module", + "dependencies": { + "vite": "^5.4.11", + "@ethercorps/sveltekit-og": "^3.0.0", + "@internationalized/date": "^3.6.0", + "@lucia-auth/adapter-postgresql": "^3.1.2", + "@lucia-auth/adapter-sqlite": "^3.0.2", + "@tailwindcss/container-queries": "^0.1.1", + "@types/cookie": "^0.6.0", + "bits-ui": "^0.21.16", + "camelcase-keys": "^9.1.3", + "capitalize": "^2.0.4", + "chalk": "^5.3.0", + "cli-progress": "^3.12.0", + "clsx": "^2.1.1", + "cmdk-sv": "^0.0.18", + "commander": "^12.1.0", + "confbox": "^0.1.8", + "cookie": "^0.6.0", + "dayjs": "^1.11.13", + "dedent": "^1.5.3", + "dotenv": "^16.4.7", + "fflate": "^0.8.2", + "formsnap": "^1.0.1", + "fuzzball": "^2.1.3", + "kysely": "^0.27.5", + "kysely-bun-sqlite": "^0.3.2", + "lucia": "^3.2.2", + "lucide-svelte": "^0.454.0", + "magic-bytes.js": "^1.10.0", + "natural-compare-lite": "^1.4.0", + "node-addon-api": "^8.3.0", + "node-gyp": "^10.3.1", + "node-html-parser": "^7.0.1", + "node-stream-zip": "^1.15.0", + "nodemailer": "^6.9.16", + "p-map": "^7.0.3", + "p-queue": "^8.0.1", + "pg": "^8.13.1", + "pretty-bytes": "^6.1.1", + "prompts": "^2.4.2", + "ramda": "^0.30.1", + "sharp": "^0.33.5", + "slugify": "^1.6.6", + "streamsaver": "^2.0.6", + "string-pixel-width": "^1.11.0", + "strip-ansi": "^7.1.0", + "svelte-dnd-action": "^0.9.53", + "svelte-meta-tags": "^3.1.4", + "svelte-sonner": "^0.3.28", + "sveltekit-superforms": "^2.22.1", + "tailwind-merge": "^2.5.5", + "tailwind-variants": "^0.2.1", + "tmp": "^0.2.3", + "ts-pattern": "^5.6.0", + "type-fest": "^4.30.2", + "windows-1252": "^3.0.4", + "xml2js": "^0.6.2", + "yaml": "^2.6.1", + "zod": "^3.24.1", + "zod-urlsearchparams": "^0.0.14" + }, + "trustedDependencies": [ + "@sveltejs/kit", + "esbuild", + "sharp", + "svelte-adapter-bun", + "svelte-preprocess" + ] +} diff --git a/test/integration/vite-build/the-test-app/postcss.config.js b/test/integration/vite-build/the-test-app/postcss.config.js new file mode 100644 index 00000000000000..1d3c89cd2f76e6 --- /dev/null +++ b/test/integration/vite-build/the-test-app/postcss.config.js @@ -0,0 +1,7 @@ +export default { + plugins: { + 'tailwindcss/nesting': {}, + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/test/integration/vite-build/the-test-app/svelte.config.js b/test/integration/vite-build/the-test-app/svelte.config.js new file mode 100644 index 00000000000000..81fa1244c4bf27 --- /dev/null +++ b/test/integration/vite-build/the-test-app/svelte.config.js @@ -0,0 +1,28 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +import adapter from '@sveltejs/adapter-node'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + preprocess: vitePreprocess(), + kit: { + files: { + appTemplate: 'app/app.html', + errorTemplate: 'app/error.html', + lib: 'app/lib', + routes: 'app/routes', + hooks: { + server: 'app/hooks.server.ts', + }, + }, + adapter: adapter({ + reusePort: true, + }), + alias: { + $assets: './app/assets', + '~shared': './shared/', + }, + csrf: false, + }, +}; + +export default config; diff --git a/test/integration/vite-build/the-test-app/tailwind.config.ts b/test/integration/vite-build/the-test-app/tailwind.config.ts new file mode 100644 index 00000000000000..7d8538c7621057 --- /dev/null +++ b/test/integration/vite-build/the-test-app/tailwind.config.ts @@ -0,0 +1,76 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +import type { Config } from 'tailwindcss'; +import { fontFamily } from 'tailwindcss/defaultTheme'; + +const config: Config = { + darkMode: ['class'], + content: ['./app/**/*.{html,js,svelte,ts}'], + safelist: ['dark'], + theme: { + container: { + center: true, + screens: { + '2xl': '1920px', + }, + }, + extend: { + colors: { + border: 'hsl(var(--border) / )', + input: 'hsl(var(--input) / )', + ring: 'hsl(var(--ring) / )', + background: 'hsl(var(--background) / )', + foreground: 'hsl(var(--foreground) / )', + primary: { + DEFAULT: 'hsl(var(--primary) / )', + foreground: 'hsl(var(--primary-foreground) / )', + }, + secondary: { + DEFAULT: 'hsl(var(--secondary) / )', + foreground: 'hsl(var(--secondary-foreground) / )', + }, + destructive: { + DEFAULT: 'hsl(var(--destructive) / )', + foreground: 'hsl(var(--destructive-foreground) / )', + }, + muted: { + DEFAULT: 'hsl(var(--muted) / )', + foreground: 'hsl(var(--muted-foreground) / )', + 'foreground-light': 'hsl(var(--muted-foreground-light) / )', + }, + accent: { + DEFAULT: 'hsl(var(--accent) / )', + foreground: 'hsl(var(--accent-foreground) / )', + }, + popover: { + DEFAULT: 'hsl(var(--popover) / )', + foreground: 'hsl(var(--popover-foreground) / )', + }, + card: { + DEFAULT: 'hsl(var(--card) / )', + foreground: 'hsl(var(--card-foreground) / )', + }, + shadow: { + DEFAULT: 'hsl(var(--shadow) / 0.125)', + }, + success: { + DEFAULT: 'hsl(var(--success) / )', + }, + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', + }, + fontFamily: { + sans: [...fontFamily.sans], + }, + screens: { + xs: '540px', + '3xl': '1920px', + }, + }, + }, + plugins: [require('@tailwindcss/container-queries')], +}; + +export default config; diff --git a/test/integration/vite-build/the-test-app/tsconfig.json b/test/integration/vite-build/the-test-app/tsconfig.json new file mode 100644 index 00000000000000..f2ac54a3c07d6f --- /dev/null +++ b/test/integration/vite-build/the-test-app/tsconfig.json @@ -0,0 +1,67 @@ +{ + "compilerOptions": { + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "isolatedModules": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, + "noUncheckedIndexedAccess": true, + "types": ["@types/bun"], + "rootDirs": ["./", "./.svelte-kit/types"], + "paths": { + "$assets": ["./app/assets"], + "$assets/*": ["./app/assets/*"], + "~shared": ["./shared"], + "~shared/*": ["./shared/*"], + "$lib": ["./app/lib"], + "$lib/*": ["./app/lib/*"] + } + }, + "include": [ + "./app/**/*.js", + "./app/**/*.ts", + "./app/**/*.svelte", + ".svelte-kit/ambient.d.ts", + "./cli/**/*.ts", + "./shared/**/*.ts", + "./.svelte-kit/ambient.d.ts", + "./.svelte-kit/non-ambient.d.ts", + "./.svelte-kit/types/**/$types.d.ts", + "./vite.config.js", + "./vite.config.ts", + "./app/routes/**/*.js", + "./app/routes/**/*.ts", + "./app/routes/**/*.svelte", + "./app/lib/**/*.js", + "./app/lib/**/*.ts", + "./app/lib/**/*.svelte", + "./src/**/*.js", + "./src/**/*.ts", + "./src/**/*.svelte", + "./tests/**/*.js", + "./tests/**/*.ts", + "./tests/**/*.svelte", + "./scripts/*.ts" + ], + "exclude": [ + "./node_modules/**", + "./src/service-worker.js", + "./src/service-worker/**/*.js", + "./src/service-worker.ts", + "./src/service-worker/**/*.ts", + "./src/service-worker.d.ts", + "./src/service-worker/**/*.d.ts" + ] +} diff --git a/test/integration/vite-build/the-test-app/vite.config.ts b/test/integration/vite-build/the-test-app/vite.config.ts new file mode 100644 index 00000000000000..796753a9a4b8e8 --- /dev/null +++ b/test/integration/vite-build/the-test-app/vite.config.ts @@ -0,0 +1,27 @@ +import { readFileSync } from 'fs'; +import { fileURLToPath } from 'url'; +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; + +const file = fileURLToPath(new URL('package.json', import.meta.url)); +const json = readFileSync(file, 'utf8'); +const pkg = JSON.parse(json); + +// const hexLoader: Plugin = { +// name: 'hex-loader', +// async transform(_code, id: string) { +// const [path, query] = id.split('?'); +// if (query != 'raw-hex') return null; + +// const data = await Bun.file(path).bytes(); +// const hex = data.toHex(); + +// return `export default '${hex}';`; +// }, +// }; + +export default defineConfig({ + server: { fs: { allow: ['app', 'shared/utils.ts'] } }, + plugins: [sveltekit()], + define: { PKG: pkg }, +}); diff --git a/test/integration/vite-build/vite-build.test.ts b/test/integration/vite-build/vite-build.test.ts new file mode 100644 index 00000000000000..eb6d8a300c845b --- /dev/null +++ b/test/integration/vite-build/vite-build.test.ts @@ -0,0 +1,31 @@ +import { test, expect } from "bun:test"; +import { tmpdirSync, bunExe, bunEnv as env, runBunInstall } from "harness"; +import fs from "fs"; +import path from "path"; + +test("vite build works", async () => { + const testDir = tmpdirSync(); + + fs.cpSync(path.join(import.meta.dir, "the-test-app"), testDir, { recursive: true, force: true }); + + const { exited: installExited } = Bun.spawn({ + cmd: [bunExe(), "install", "--ignore-scripts"], + cwd: testDir, + env, + }); + + expect(await installExited).toBe(0); + + const { stdout, stderr, exited } = Bun.spawn({ + cmd: [bunExe(), "node_modules/vite/bin/vite.js", "build"], + cwd: testDir, + stdout: "pipe", + stderr: "inherit", + env, + }); + + expect(await exited).toBe(0); + + const out = await Bun.readableStreamToText(stdout); + expect(out).toContain("done"); +}, 60_000); diff --git a/test/js/bun/bun-object/deep-equals.spec.ts b/test/js/bun/bun-object/deep-equals.spec.ts new file mode 100644 index 00000000000000..323280114b151f --- /dev/null +++ b/test/js/bun/bun-object/deep-equals.spec.ts @@ -0,0 +1,58 @@ +describe.each([true, false])("Bun.deepEquals(a, b, strict: %p)", strict => { + const deepEquals = (a: unknown, b: unknown) => Bun.deepEquals(a, b, strict); + it.each([ + [1, 1], + [true, true], + [undefined, undefined], + [null, null], + ["foo", "foo"], + [{}, {}], + [{ a: 1 }, { a: 1 }], + [new Map(), new Map()], + [new Set(), new Set()], + [Symbol.for("foo"), Symbol.for("foo")], + [NaN, NaN], + ])("Bun.deepEquals(%p, %p) === true, regardless of strict modee", (a, b) => { + expect(Bun.deepEquals(a, b, true)).toBe(true); + expect(Bun.deepEquals(a, b, false)).toBe(true); + }); + + it.each([ + [0, 1], + [-0, +0], // + [{ a: 1 }, { a: 2 }], + ["foo", "bar"], + ])("Bun.deepEquals(%p, %p) !== true, regardless of strict modee", (a, b) => { + expect(Bun.deepEquals(a, b, true)).toBe(false); + expect(Bun.deepEquals(a, b, false)).toBe(false); + }); + + // https://github.com/nodejs/node/issues/10258 + it("fake dates are not equal", () => { + function FakeDate() {} + FakeDate.prototype = Date.prototype; + const a = new Date("2016"); + const b = new FakeDate(); + expect(deepEquals(a, b)).toBe(false); + expect(deepEquals(b, a)).toBe(false); + }); + + it("fake maps are not equal", () => { + function FakeMap() {} + FakeMap.prototype = Map.prototype; + const a = new Map(); + const b = new FakeMap(); + expect(deepEquals(a, b)).toBe(false); + expect(deepEquals(b, a)).toBe(false); + }); + + // we may change this in the future + it("functions that are not reference-equal are never equal", () => { + function foo() {} + function bar() {} + function baz(a) {} + expect(deepEquals(foo, foo)).toBe(true); + expect(deepEquals(foo, bar)).toBe(false); + expect(deepEquals(foo, baz)).toBe(false); + }); +}); diff --git a/test/js/bun/css/css.test.ts b/test/js/bun/css/css.test.ts index 3e256d1e8eff5a..375e1317272802 100644 --- a/test/js/bun/css/css.test.ts +++ b/test/js/bun/css/css.test.ts @@ -16,6 +16,10 @@ import { ParserOptions, } from "./util"; +function Some(n: number): number { + return n; +} + function error_test(css: string, error: unknown) { // going to ignore this test for now test.skip(`ERROR: ${css}`, () => {}); @@ -1296,19 +1300,19 @@ describe("css tests", () => { ` .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { border-left-color: #b32323; - border-left-color: color(display-p3 .6433075 .19245467 .1677117); + border-left-color: color(display-p3 .643308 .192455 .167712); border-left-color: lab(40% 56.6 39); border-right-color: #ee00be; - border-right-color: color(display-p3 .9729615 -.36207756 .80420625); + border-right-color: color(display-p3 .972961 -.362078 .804206); border-right-color: lch(50.998% 135.363 338); } .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { border-left-color: #ee00be; - border-left-color: color(display-p3 .9729615 -.36207756 .80420625); + border-left-color: color(display-p3 .972961 -.362078 .804206); border-left-color: lch(50.998% 135.363 338); border-right-color: #b32323; - border-right-color: color(display-p3 .6433075 .19245467 .1677117); + border-right-color: color(display-p3 .643308 .192455 .167712); border-right-color: lab(40% 56.6 39); } `, @@ -1576,6 +1580,175 @@ describe("css tests", () => { ); }); + describe("box-shadow", () => { + minify_test( + ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4) }", + ".foo{box-shadow:64px 64px 12px 40px #0006}", + ); + minify_test( + ".foo { box-shadow: 12px 12px 0px 8px rgba(0,0,0,0.4) inset }", + ".foo{box-shadow:inset 12px 12px 0 8px #0006}", + ); + minify_test( + ".foo { box-shadow: inset 12px 12px 0px 8px rgba(0,0,0,0.4) }", + ".foo{box-shadow:inset 12px 12px 0 8px #0006}", + ); + minify_test(".foo { box-shadow: 12px 12px 8px 0px rgba(0,0,0,0.4) }", ".foo{box-shadow:12px 12px 8px #0006}"); + minify_test(".foo { box-shadow: 12px 12px 0px 0px rgba(0,0,0,0.4) }", ".foo{box-shadow:12px 12px #0006}"); + minify_test( + ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4), 12px 12px 0px 8px rgba(0,0,0,0.4) inset }", + ".foo{box-shadow:64px 64px 12px 40px #0006,inset 12px 12px 0 8px #0006}", + ); + + prefix_test( + ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }", + `.foo { + box-shadow: 12px 12px #b32323; + box-shadow: 12px 12px lab(40% 56.6 39); + } + `, + { chrome: Some(90 << 16) }, + ); + + prefix_test( + ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }", + `.foo { + -webkit-box-shadow: 12px 12px #b32323; + box-shadow: 12px 12px #b32323; + box-shadow: 12px 12px lab(40% 56.6 39); + } + `, + { chrome: Some(4 << 16) }, + ); + + prefix_test( + ".foo { box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }", + `.foo { + -webkit-box-shadow: 12px 12px #b32323, 12px 12px #ff0; + box-shadow: 12px 12px #b32323, 12px 12px #ff0; + box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0; + } + `, + { chrome: Some(4 << 16) }, + ); + + prefix_test( + ".foo { -webkit-box-shadow: 12px 12px #0006 }", + `.foo { + -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4); + } + `, + { chrome: Some(4 << 16) }, + ); + + prefix_test( + `.foo { + -webkit-box-shadow: 12px 12px #0006; + -moz-box-shadow: 12px 12px #0009; + }`, + `.foo { + -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4); + -moz-box-shadow: 12px 12px rgba(0, 0, 0, .6); + } + `, + { chrome: Some(4 << 16) }, + ); + + prefix_test( + `.foo { + -webkit-box-shadow: 12px 12px #0006; + -moz-box-shadow: 12px 12px #0006; + box-shadow: 12px 12px #0006; + }`, + `.foo { + box-shadow: 12px 12px #0006; + } + `, + { chrome: Some(95 << 16) }, + ); + + prefix_test( + ".foo { box-shadow: var(--foo) 12px lab(40% 56.6 39) }", + `.foo { + box-shadow: var(--foo) 12px #b32323; + } + + @supports (color: lab(0% 0 0)) { + .foo { + box-shadow: var(--foo) 12px lab(40% 56.6 39); + } + } + `, + { chrome: Some(90 << 16) }, + ); + + prefix_test( + `.foo { + box-shadow: 0px 0px 22px red; + box-shadow: 0px 0px max(2cqw, 22px) red; + } + `, + `.foo { + box-shadow: 0 0 22px red; + box-shadow: 0 0 max(2cqw, 22px) red; + } + `, + { safari: Some(14 << 16) }, + ); + prefix_test( + `.foo { + box-shadow: 0px 0px 22px red; + box-shadow: 0px 0px max(2cqw, 22px) red; + } + `, + `.foo { + box-shadow: 0 0 max(2cqw, 22px) red; + } + `, + { safari: Some(16 << 16) }, + ); + + prefix_test( + `.foo { + box-shadow: 0px 0px 22px red; + box-shadow: 0px 0px 22px lab(40% 56.6 39); + } + `, + `.foo { + box-shadow: 0 0 22px red; + box-shadow: 0 0 22px lab(40% 56.6 39); + } + `, + { safari: Some(14 << 16) }, + ); + prefix_test( + `.foo { + box-shadow: 0px 0px 22px red; + box-shadow: 0px 0px 22px lab(40% 56.6 39); + } + `, + `.foo { + box-shadow: 0 0 22px lab(40% 56.6 39); + } + `, + { safari: Some(16 << 16) }, + ); + + prefix_test( + `.foo { + box-shadow: var(--fallback); + box-shadow: 0px 0px 22px lab(40% 56.6 39); + } + `, + `.foo { + box-shadow: var(--fallback); + box-shadow: 0 0 22px lab(40% 56.6 39); + } + `, + { safari: Some(16 << 16) }, + ); + }); + describe("margin", () => { cssTest( ` @@ -3258,270 +3431,270 @@ describe("css tests", () => { `, ); - // cssTest( - // ` - // .foo { - // align-content: center; - // justify-content: center; - // } - // `, - // ` - // .foo { - // place-content: center; - // } - // `, - // ); - - // cssTest( - // ` - // .foo { - // align-content: first baseline; - // justify-content: safe right; - // } - // `, - // ` - // .foo { - // place-content: baseline safe right; - // } - // `, - // ); - - // cssTest( - // ` - // .foo { - // place-content: first baseline unsafe left; - // } - // `, - // ` - // .foo { - // place-content: baseline unsafe left; - // } - // `, - // ); + cssTest( + ` + .foo { + align-content: center; + justify-content: center; + } + `, + ` + .foo { + place-content: center; + } + `, + ); - // cssTest( - // ` - // .foo { - // place-content: center center; - // } - // `, - // ` - // .foo { - // place-content: center; - // } - // `, - // ); + cssTest( + ` + .foo { + align-content: first baseline; + justify-content: safe right; + } + `, + ` + .foo { + place-content: baseline safe right; + } + `, + ); - // cssTest( - // ` - // .foo { - // align-self: center; - // justify-self: center; - // } - // `, - // ` - // .foo { - // place-self: center; - // } - // `, - // ); + cssTest( + ` + .foo { + place-content: first baseline unsafe left; + } + `, + ` + .foo { + place-content: baseline unsafe left; + } + `, + ); - // cssTest( - // ` - // .foo { - // align-self: center; - // justify-self: unsafe left; - // } - // `, - // ` - // .foo { - // place-self: center unsafe left; - // } - // `, - // ); + cssTest( + ` + .foo { + place-content: center center; + } + `, + ` + .foo { + place-content: center; + } + `, + ); - // cssTest( - // ` - // .foo { - // align-items: center; - // justify-items: center; - // } - // `, - // ` - // .foo { - // place-items: center; - // } - // `, - // ); + cssTest( + ` + .foo { + align-self: center; + justify-self: center; + } + `, + ` + .foo { + place-self: center; + } + `, + ); - // cssTest( - // ` - // .foo { - // align-items: center; - // justify-items: legacy left; - // } - // `, - // ` - // .foo { - // place-items: center legacy left; - // } - // `, - // ); + cssTest( + ` + .foo { + align-self: center; + justify-self: unsafe left; + } + `, + ` + .foo { + place-self: center unsafe left; + } + `, + ); - // cssTest( - // ` - // .foo { - // place-items: center; - // justify-items: var(--justify); - // } - // `, - // ` - // .foo { - // place-items: center; - // justify-items: var(--justify); - // } - // `, - // ); + cssTest( + ` + .foo { + align-items: center; + justify-items: center; + } + `, + ` + .foo { + place-items: center; + } + `, + ); - // cssTest( - // ` - // .foo { - // row-gap: 10px; - // column-gap: 20px; - // } - // `, - // ` - // .foo { - // gap: 10px 20px; - // } - // `, - // ); + cssTest( + ` + .foo { + align-items: center; + justify-items: legacy left; + } + `, + ` + .foo { + place-items: center legacy left; + } + `, + ); - // cssTest( - // ` - // .foo { - // row-gap: 10px; - // column-gap: 10px; - // } - // `, - // ` - // .foo { - // gap: 10px; - // } - // `, - // ); + cssTest( + ` + .foo { + place-items: center; + justify-items: var(--justify); + } + `, + ` + .foo { + place-items: center; + justify-items: var(--justify); + } + `, + ); - // cssTest( - // ` - // .foo { - // gap: 10px; - // column-gap: 20px; - // } - // `, - // ` - // .foo { - // gap: 10px 20px; - // } - // `, - // ); + cssTest( + ` + .foo { + row-gap: 10px; + column-gap: 20px; + } + `, + ` + .foo { + gap: 10px 20px; + } + `, + ); - // cssTest( - // ` - // .foo { - // column-gap: 20px; - // gap: 10px; - // } - // `, - // ` - // .foo { - // gap: 10px; - // } - // `, - // ); + cssTest( + ` + .foo { + row-gap: 10px; + column-gap: 10px; + } + `, + ` + .foo { + gap: 10px; + } + `, + ); - // cssTest( - // ` - // .foo { - // row-gap: normal; - // column-gap: 20px; - // } - // `, - // ` - // .foo { - // gap: normal 20px; - // } - // `, - // ); + cssTest( + ` + .foo { + gap: 10px; + column-gap: 20px; + } + `, + ` + .foo { + gap: 10px 20px; + } + `, + ); cssTest( ` - .foo { - -webkit-flex-grow: 1; - -webkit-flex-shrink: 1; - -webkit-flex-basis: auto; - } - `, + .foo { + column-gap: 20px; + gap: 10px; + } + `, ` - .foo { - -webkit-flex: auto; - } - `, + .foo { + gap: 10px; + } + `, ); + cssTest( ` - .foo { - -webkit-flex-grow: 1; - -webkit-flex-shrink: 1; - -webkit-flex-basis: auto; - flex-grow: 1; - flex-shrink: 1; - flex-basis: auto; - } - `, + .foo { + row-gap: normal; + column-gap: 20px; + } + `, ` - .foo { - -webkit-flex: auto; - flex: auto; - } - `, + .foo { + gap: normal 20px; + } + `, ); - prefix_test( + + cssTest( ` - .foo { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - flex-direction: row; - } - `, + .foo { + -webkit-flex-grow: 1; + -webkit-flex-shrink: 1; + -webkit-flex-basis: auto; + } + `, ` - .foo { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -webkit-flex-direction: row; - flex-direction: row; - } - `, + .foo { + -webkit-flex: auto; + } + `, + ); + cssTest( + ` + .foo { + -webkit-flex-grow: 1; + -webkit-flex-shrink: 1; + -webkit-flex-basis: auto; + flex-grow: 1; + flex-shrink: 1; + flex-basis: auto; + } + `, + ` + .foo { + -webkit-flex: auto; + flex: auto; + } + `, + ); + prefix_test( + ` + .foo { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + flex-direction: row; + } + `, + ` + .foo { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + flex-direction: row; + } + `, { safari: 4 << 16, }, ); prefix_test( ` - .foo { - flex-direction: row; - } - `, + .foo { + flex-direction: row; + } + `, ` - .foo { - -webkit-box-orient: horizontal; - -moz-box-orient: horizontal; - -webkit-box-direction: normal; - -moz-box-direction: normal; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - } - `, + .foo { + -webkit-box-orient: horizontal; + -moz-box-orient: horizontal; + -webkit-box-direction: normal; + -moz-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3530,40 +3703,40 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -moz-box-orient: horizontal; - -moz-box-direction: normal; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - } - `, + .foo { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -moz-box-orient: horizontal; + -moz-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + } + `, ` - .foo { - flex-direction: row; - } - `, + .foo { + flex-direction: row; + } + `, { safari: 14 << 16, }, ); prefix_test( ` - .foo { - flex-wrap: wrap; - } - `, + .foo { + flex-wrap: wrap; + } + `, ` - .foo { - -webkit-box-lines: multiple; - -moz-box-lines: multiple; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - } - `, + .foo { + -webkit-box-lines: multiple; + -moz-box-lines: multiple; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3572,40 +3745,40 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -webkit-box-lines: multiple; - -moz-box-lines: multiple; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - } - `, + .foo { + -webkit-box-lines: multiple; + -moz-box-lines: multiple; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + } + `, ` - .foo { - flex-wrap: wrap; - } - `, + .foo { + flex-wrap: wrap; + } + `, { safari: 11 << 16, }, ); prefix_test( ` - .foo { - flex-flow: row wrap; - } - `, + .foo { + flex-flow: row wrap; + } + `, ` - .foo { - -webkit-box-orient: horizontal; - -moz-box-orient: horizontal; - -webkit-box-direction: normal; - -moz-box-direction: normal; - -webkit-flex-flow: wrap; - -ms-flex-flow: wrap; - flex-flow: wrap; - } - `, + .foo { + -webkit-box-orient: horizontal; + -moz-box-orient: horizontal; + -webkit-box-direction: normal; + -moz-box-direction: normal; + -webkit-flex-flow: wrap; + -ms-flex-flow: wrap; + flex-flow: wrap; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3614,40 +3787,40 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -webkit-box-orient: horizontal; - -moz-box-orient: horizontal; - -webkit-box-direction: normal; - -moz-box-direction: normal; - -webkit-flex-flow: wrap; - -ms-flex-flow: wrap; - flex-flow: wrap; - } - `, + .foo { + -webkit-box-orient: horizontal; + -moz-box-orient: horizontal; + -webkit-box-direction: normal; + -moz-box-direction: normal; + -webkit-flex-flow: wrap; + -ms-flex-flow: wrap; + flex-flow: wrap; + } + `, ` - .foo { - flex-flow: wrap; - } - `, + .foo { + flex-flow: wrap; + } + `, { safari: 11 << 16, }, ); prefix_test( ` - .foo { - flex-grow: 1; - } - `, + .foo { + flex-grow: 1; + } + `, ` - .foo { - -webkit-box-flex: 1; - -moz-box-flex: 1; - -ms-flex-positive: 1; - -webkit-flex-grow: 1; - flex-grow: 1; - } - `, + .foo { + -webkit-box-flex: 1; + -moz-box-flex: 1; + -ms-flex-positive: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3656,36 +3829,36 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -webkit-box-flex: 1; - -moz-box-flex: 1; - -ms-flex-positive: 1; - -webkit-flex-grow: 1; - flex-grow: 1; - } - `, + .foo { + -webkit-box-flex: 1; + -moz-box-flex: 1; + -ms-flex-positive: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + } + `, ` - .foo { - flex-grow: 1; - } - `, + .foo { + flex-grow: 1; + } + `, { safari: 11 << 16, }, ); prefix_test( ` - .foo { - flex-shrink: 1; - } - `, + .foo { + flex-shrink: 1; + } + `, ` - .foo { - -ms-flex-negative: 1; - -webkit-flex-shrink: 1; - flex-shrink: 1; - } - `, + .foo { + -ms-flex-negative: 1; + -webkit-flex-shrink: 1; + flex-shrink: 1; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3694,34 +3867,34 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -ms-flex-negative: 1; - -webkit-flex-shrink: 1; - flex-shrink: 1; - } - `, + .foo { + -ms-flex-negative: 1; + -webkit-flex-shrink: 1; + flex-shrink: 1; + } + `, ` - .foo { - flex-shrink: 1; - } - `, + .foo { + flex-shrink: 1; + } + `, { safari: 11 << 16, }, ); prefix_test( ` - .foo { - flex-basis: 1px; - } - `, + .foo { + flex-basis: 1px; + } + `, ` - .foo { - -ms-flex-preferred-size: 1px; - -webkit-flex-basis: 1px; - flex-basis: 1px; - } - `, + .foo { + -ms-flex-preferred-size: 1px; + -webkit-flex-basis: 1px; + flex-basis: 1px; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3730,36 +3903,36 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -ms-flex-preferred-size: 1px; - -webkit-flex-basis: 1px; - flex-basis: 1px; - } - `, + .foo { + -ms-flex-preferred-size: 1px; + -webkit-flex-basis: 1px; + flex-basis: 1px; + } + `, ` - .foo { - flex-basis: 1px; - } - `, + .foo { + flex-basis: 1px; + } + `, { safari: 11 << 16, }, ); prefix_test( ` - .foo { - flex: 1; - } - `, + .foo { + flex: 1; + } + `, ` - .foo { - -webkit-box-flex: 1; - -moz-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - } - `, + .foo { + -webkit-box-flex: 1; + -moz-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -3768,391 +3941,36 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -webkit-box-flex: 1; - -moz-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - } - `, + .foo { + -webkit-box-flex: 1; + -moz-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + } + `, ` - .foo { - flex: 1; - } - `, + .foo { + flex: 1; + } + `, { safari: 11 << 16, }, ); - // prefix_test( - // ` - // .foo { - // align-content: space-between; - // } - // `, - // ` - // .foo { - // -ms-flex-line-pack: justify; - // -webkit-align-content: space-between; - // align-content: space-between; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -ms-flex-line-pack: justify; - // -webkit-align-content: space-between; - // align-content: space-between; - // } - // `, - // ` - // .foo { - // align-content: space-between; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // justify-content: space-between; - // } - // `, - // ` - // .foo { - // -webkit-box-pack: justify; - // -moz-box-pack: justify; - // -ms-flex-pack: justify; - // -webkit-justify-content: space-between; - // justify-content: space-between; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -webkit-box-pack: justify; - // -moz-box-pack: justify; - // -ms-flex-pack: justify; - // -webkit-justify-content: space-between; - // justify-content: space-between; - // } - // `, - // ` - // .foo { - // justify-content: space-between; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-content: space-between flex-end; - // } - // `, - // ` - // .foo { - // -ms-flex-line-pack: justify; - // -webkit-box-pack: end; - // -moz-box-pack: end; - // -ms-flex-pack: end; - // -webkit-align-content: space-between; - // align-content: space-between; - // -webkit-justify-content: flex-end; - // justify-content: flex-end; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -ms-flex-line-pack: justify; - // -webkit-box-pack: end; - // -moz-box-pack: end; - // -ms-flex-pack: end; - // -webkit-align-content: space-between; - // -webkit-justify-content: flex-end; - // place-content: space-between flex-end; - // } - // `, - // ` - // .foo { - // place-content: space-between flex-end; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-content: space-between flex-end; - // } - // `, - // ` - // .foo { - // align-content: space-between; - // justify-content: flex-end; - // } - // `, - // { - // chrome: 30 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-content: space-between flex-end; - // } - // `, - // ` - // .foo { - // place-content: space-between flex-end; - // } - // `, - // { - // chrome: 60 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // align-self: flex-end; - // } - // `, - // ` - // .foo { - // -ms-flex-item-align: end; - // -webkit-align-self: flex-end; - // align-self: flex-end; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -ms-flex-item-align: end; - // -webkit-align-self: flex-end; - // align-self: flex-end; - // } - // `, - // ` - // .foo { - // align-self: flex-end; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-self: center flex-end; - // } - // `, - // ` - // .foo { - // -ms-flex-item-align: center; - // -webkit-align-self: center; - // align-self: center; - // justify-self: flex-end; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -ms-flex-item-align: center; - // -webkit-align-self: center; - // place-self: center flex-end; - // } - // `, - // ` - // .foo { - // place-self: center flex-end; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-self: center flex-end; - // } - // `, - // ` - // .foo { - // align-self: center; - // justify-self: flex-end; - // } - // `, - // { - // chrome: 57 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-self: center flex-end; - // } - // `, - // ` - // .foo { - // place-self: center flex-end; - // } - // `, - // { - // chrome: 59 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // align-items: flex-end; - // } - // `, - // ` - // .foo { - // -webkit-box-align: end; - // -moz-box-align: end; - // -ms-flex-align: end; - // -webkit-align-items: flex-end; - // align-items: flex-end; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -webkit-box-align: end; - // -moz-box-align: end; - // -ms-flex-align: end; - // -webkit-align-items: flex-end; - // align-items: flex-end; - // } - // `, - // ` - // .foo { - // align-items: flex-end; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-items: flex-end center; - // } - // `, - // ` - // .foo { - // -webkit-box-align: end; - // -moz-box-align: end; - // -ms-flex-align: end; - // -webkit-align-items: flex-end; - // align-items: flex-end; - // justify-items: center; - // } - // `, - // { - // safari: 4 << 16, - // firefox: 4 << 16, - // ie: 10 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // -webkit-box-align: end; - // -moz-box-align: end; - // -ms-flex-align: end; - // -webkit-align-items: flex-end; - // place-items: flex-end center; - // } - // `, - // ` - // .foo { - // place-items: flex-end center; - // } - // `, - // { - // safari: 11 << 16, - // }, - // ); - // prefix_test( - // ` - // .foo { - // place-items: flex-end center; - // } - // `, - // ` - // .foo { - // align-items: flex-end; - // justify-items: center; - // } - // `, - // { - // safari: 10 << 16, - // }, - // ); prefix_test( ` - .foo { - order: 1; - } - `, + .foo { + align-content: space-between; + } + `, ` - .foo { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; - order: 1; - } - `, + .foo { + -ms-flex-line-pack: justify; + -webkit-align-content: space-between; + align-content: space-between; + } + `, { safari: 4 << 16, firefox: 4 << 16, @@ -4161,36 +3979,391 @@ describe("css tests", () => { ); prefix_test( ` - .foo { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; - order: 1; - } - `, + .foo { + -ms-flex-line-pack: justify; + -webkit-align-content: space-between; + align-content: space-between; + } + `, ` - .foo { - order: 1; - } - `, + .foo { + align-content: space-between; + } + `, { safari: 11 << 16, }, ); prefix_test( ` - .foo { - -ms-flex: 0 0 8%; - flex: 0 0 5%; - } - `, + .foo { + justify-content: space-between; + } + `, ` - .foo { - -ms-flex: 0 0 8%; - flex: 0 0 5%; - } - `, + .foo { + -webkit-box-pack: justify; + -moz-box-pack: justify; + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -webkit-box-pack: justify; + -moz-box-pack: justify; + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + } + `, + ` + .foo { + justify-content: space-between; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + place-content: space-between flex-end; + } + `, + ` + .foo { + -ms-flex-line-pack: justify; + -webkit-box-pack: end; + -moz-box-pack: end; + -ms-flex-pack: end; + -webkit-align-content: space-between; + align-content: space-between; + -webkit-justify-content: flex-end; + justify-content: flex-end; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -ms-flex-line-pack: justify; + -webkit-box-pack: end; + -moz-box-pack: end; + -ms-flex-pack: end; + -webkit-align-content: space-between; + -webkit-justify-content: flex-end; + place-content: space-between flex-end; + } + `, + ` + .foo { + place-content: space-between flex-end; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + place-content: space-between flex-end; + } + `, + ` + .foo { + align-content: space-between; + justify-content: flex-end; + } + `, + { + chrome: 30 << 16, + }, + ); + prefix_test( + ` + .foo { + place-content: space-between flex-end; + } + `, + ` + .foo { + place-content: space-between flex-end; + } + `, + { + chrome: 60 << 16, + }, + ); + prefix_test( + ` + .foo { + align-self: flex-end; + } + `, + ` + .foo { + -ms-flex-item-align: end; + -webkit-align-self: flex-end; + align-self: flex-end; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -ms-flex-item-align: end; + -webkit-align-self: flex-end; + align-self: flex-end; + } + `, + ` + .foo { + align-self: flex-end; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + place-self: center flex-end; + } + `, + ` + .foo { + -ms-flex-item-align: center; + -webkit-align-self: center; + align-self: center; + justify-self: flex-end; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -ms-flex-item-align: center; + -webkit-align-self: center; + place-self: center flex-end; + } + `, + ` + .foo { + place-self: center flex-end; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + place-self: center flex-end; + } + `, + ` + .foo { + align-self: center; + justify-self: flex-end; + } + `, + { + chrome: 57 << 16, + }, + ); + prefix_test( + ` + .foo { + place-self: center flex-end; + } + `, + ` + .foo { + place-self: center flex-end; + } + `, + { + chrome: 59 << 16, + }, + ); + prefix_test( + ` + .foo { + align-items: flex-end; + } + `, + ` + .foo { + -webkit-box-align: end; + -moz-box-align: end; + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -webkit-box-align: end; + -moz-box-align: end; + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + } + `, + ` + .foo { + align-items: flex-end; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + place-items: flex-end center; + } + `, + ` + .foo { + -webkit-box-align: end; + -moz-box-align: end; + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + justify-items: center; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -webkit-box-align: end; + -moz-box-align: end; + -ms-flex-align: end; + -webkit-align-items: flex-end; + place-items: flex-end center; + } + `, + ` + .foo { + place-items: flex-end center; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + place-items: flex-end center; + } + `, + ` + .foo { + align-items: flex-end; + justify-items: center; + } + `, + { + safari: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + order: 1; + } + `, + ` + .foo { + -webkit-box-ordinal-group: 1; + -moz-box-ordinal-group: 1; + -ms-flex-order: 1; + -webkit-order: 1; + order: 1; + } + `, + { + safari: 4 << 16, + firefox: 4 << 16, + ie: 10 << 16, + }, + ); + prefix_test( + ` + .foo { + -webkit-box-ordinal-group: 1; + -moz-box-ordinal-group: 1; + -ms-flex-order: 1; + -webkit-order: 1; + order: 1; + } + `, + ` + .foo { + order: 1; + } + `, + { + safari: 11 << 16, + }, + ); + prefix_test( + ` + .foo { + -ms-flex: 0 0 8%; + flex: 0 0 5%; + } + `, + ` + .foo { + -ms-flex: 0 0 8%; + flex: 0 0 5%; + } + `, { safari: 11 << 16, }, @@ -6083,4 +6256,972 @@ describe("css tests", () => { error_test("@media (grid: 10) { .foo { color: chartreuse }}", "ParserError::InvalidMediaQuery"); error_test("@media (prefers-color-scheme = dark) { .foo { color: chartreuse }}", "ParserError::InvalidMediaQuery"); }); + + describe("transition", () => { + minify_test(".foo { transition-duration: 500ms }", ".foo{transition-duration:.5s}"); + minify_test(".foo { transition-duration: .5s }", ".foo{transition-duration:.5s}"); + minify_test(".foo { transition-duration: 99ms }", ".foo{transition-duration:99ms}"); + minify_test(".foo { transition-duration: .099s }", ".foo{transition-duration:99ms}"); + minify_test(".foo { transition-duration: 2000ms }", ".foo{transition-duration:2s}"); + minify_test(".foo { transition-duration: 2s }", ".foo{transition-duration:2s}"); + minify_test(".foo { transition-duration: calc(1s - 50ms) }", ".foo{transition-duration:.95s}"); + minify_test(".foo { transition-duration: calc(1s - 50ms + 2s) }", ".foo{transition-duration:2.95s}"); + minify_test(".foo { transition-duration: calc((1s - 50ms) * 2) }", ".foo{transition-duration:1.9s}"); + minify_test(".foo { transition-duration: calc(2 * (1s - 50ms)) }", ".foo{transition-duration:1.9s}"); + minify_test(".foo { transition-duration: calc((2s + 50ms) - (1s - 50ms)) }", ".foo{transition-duration:1.1s}"); + minify_test(".foo { transition-duration: 500ms, 50ms }", ".foo{transition-duration:.5s,50ms}"); + minify_test(".foo { transition-delay: 500ms }", ".foo{transition-delay:.5s}"); + minify_test(".foo { transition-property: background }", ".foo{transition-property:background}"); + minify_test(".foo { transition-property: background, opacity }", ".foo{transition-property:background,opacity}"); + minify_test(".foo { transition-timing-function: linear }", ".foo{transition-timing-function:linear}"); + minify_test(".foo { transition-timing-function: ease }", ".foo{transition-timing-function:ease}"); + minify_test(".foo { transition-timing-function: ease-in }", ".foo{transition-timing-function:ease-in}"); + minify_test(".foo { transition-timing-function: ease-out }", ".foo{transition-timing-function:ease-out}"); + minify_test(".foo { transition-timing-function: ease-in-out }", ".foo{transition-timing-function:ease-in-out}"); + minify_test( + ".foo { transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1) }", + ".foo{transition-timing-function:ease}", + ); + minify_test( + ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1) }", + ".foo{transition-timing-function:ease-in}", + ); + minify_test( + ".foo { transition-timing-function: cubic-bezier(0, 0, 0.58, 1) }", + ".foo{transition-timing-function:ease-out}", + ); + minify_test( + ".foo { transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1) }", + ".foo{transition-timing-function:ease-in-out}", + ); + minify_test( + ".foo { transition-timing-function: cubic-bezier(0.58, 0.2, 0.11, 1.2) }", + ".foo{transition-timing-function:cubic-bezier(.58,.2,.11,1.2)}", + ); + minify_test(".foo { transition-timing-function: step-start }", ".foo{transition-timing-function:step-start}"); + minify_test(".foo { transition-timing-function: step-end }", ".foo{transition-timing-function:step-end}"); + minify_test(".foo { transition-timing-function: steps(1, start) }", ".foo{transition-timing-function:step-start}"); + minify_test( + ".foo { transition-timing-function: steps(1, jump-start) }", + ".foo{transition-timing-function:step-start}", + ); + minify_test(".foo { transition-timing-function: steps(1, end) }", ".foo{transition-timing-function:step-end}"); + minify_test(".foo { transition-timing-function: steps(1, jump-end) }", ".foo{transition-timing-function:step-end}"); + minify_test( + ".foo { transition-timing-function: steps(5, jump-start) }", + ".foo{transition-timing-function:steps(5,start)}", + ); + minify_test( + ".foo { transition-timing-function: steps(5, jump-end) }", + ".foo{transition-timing-function:steps(5,end)}", + ); + minify_test( + ".foo { transition-timing-function: steps(5, jump-both) }", + ".foo{transition-timing-function:steps(5,jump-both)}", + ); + minify_test( + ".foo { transition-timing-function: ease-in-out, cubic-bezier(0.42, 0, 1, 1) }", + ".foo{transition-timing-function:ease-in-out,ease-in}", + ); + minify_test( + ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1), cubic-bezier(0.58, 0.2, 0.11, 1.2) }", + ".foo{transition-timing-function:ease-in,cubic-bezier(.58,.2,.11,1.2)}", + ); + minify_test( + ".foo { transition-timing-function: step-start, steps(5, jump-start) }", + ".foo{transition-timing-function:step-start,steps(5,start)}", + ); + minify_test(".foo { transition: width 2s ease }", ".foo{transition:width 2s}"); + minify_test( + ".foo { transition: width 2s ease, height 1000ms cubic-bezier(0.25, 0.1, 0.25, 1) }", + ".foo{transition:width 2s,height 1s}", + ); + minify_test(".foo { transition: width 2s 1s }", ".foo{transition:width 2s 1s}"); + minify_test(".foo { transition: width 2s ease 1s }", ".foo{transition:width 2s 1s}"); + minify_test(".foo { transition: ease-in 1s width 4s }", ".foo{transition:width 1s ease-in 4s}"); + minify_test(".foo { transition: opacity 0s .6s }", ".foo{transition:opacity 0s .6s}"); + cssTest( + ` + .foo { + transition-property: opacity; + transition-duration: 0.09s; + transition-timing-function: ease-in-out; + transition-delay: 500ms; + } + `, + ` + .foo { + transition: opacity 90ms ease-in-out .5s; + } + `, + ); + cssTest( + ` + .foo { + transition: opacity 2s; + transition-timing-function: ease; + transition-delay: 500ms; + } + `, + ` + .foo { + transition: opacity 2s .5s; + } + `, + ); + cssTest( + ` + .foo { + transition: opacity 500ms; + transition-timing-function: var(--ease); + } + `, + ` + .foo { + transition: opacity .5s; + transition-timing-function: var(--ease); + } + `, + ); + cssTest( + ` + .foo { + transition-property: opacity; + transition-duration: 0.09s; + transition-timing-function: ease-in-out; + transition-delay: 500ms; + transition: color 2s; + } + `, + ` + .foo { + transition: color 2s; + } + `, + ); + cssTest( + ` + .foo { + transition-property: opacity, color; + transition-duration: 2s, 4s; + transition-timing-function: ease-in-out, ease-in; + transition-delay: 500ms, 0s; + } + `, + ` + .foo { + transition: opacity 2s ease-in-out .5s, color 4s ease-in; + } + `, + ); + cssTest( + ` + .foo { + transition-property: opacity, color; + transition-duration: 2s; + transition-timing-function: ease-in-out; + transition-delay: 500ms; + } + `, + ` + .foo { + transition: opacity 2s ease-in-out .5s, color 2s ease-in-out .5s; + } + `, + ); + cssTest( + ` + .foo { + transition-property: opacity, color, width, height; + transition-duration: 2s, 4s; + transition-timing-function: ease; + transition-delay: 0s; + } + `, + ` + .foo { + transition: opacity 2s, color 4s, width 2s, height 4s; + } + `, + ); + + cssTest( + ` + .foo { + -webkit-transition-property: opacity, color; + -webkit-transition-duration: 2s, 4s; + -webkit-transition-timing-function: ease-in-out, ease-in; + -webkit-transition-delay: 500ms, 0s; + } + `, + ` + .foo { + -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in; + } + `, + ); + + cssTest( + ` + .foo { + -webkit-transition-property: opacity, color; + -webkit-transition-duration: 2s, 4s; + -webkit-transition-timing-function: ease-in-out, ease-in; + -webkit-transition-delay: 500ms, 0s; + -moz-transition-property: opacity, color; + -moz-transition-duration: 2s, 4s; + -moz-transition-timing-function: ease-in-out, ease-in; + -moz-transition-delay: 500ms, 0s; + transition-property: opacity, color; + transition-duration: 2s, 4s; + transition-timing-function: ease-in-out, ease-in; + transition-delay: 500ms, 0s; + } + `, + ` + .foo { + -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in; + -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in; + transition: opacity 2s ease-in-out .5s, color 4s ease-in; + } + `, + ); + + cssTest( + ` + .foo { + -webkit-transition-property: opacity, color; + -moz-transition-property: opacity, color; + transition-property: opacity, color; + -webkit-transition-duration: 2s, 4s; + -moz-transition-duration: 2s, 4s; + transition-duration: 2s, 4s; + -webkit-transition-timing-function: ease-in-out, ease-in; + transition-timing-function: ease-in-out, ease-in; + -moz-transition-timing-function: ease-in-out, ease-in; + -webkit-transition-delay: 500ms, 0s; + -moz-transition-delay: 500ms, 0s; + transition-delay: 500ms, 0s; + } + `, + ` + .foo { + -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in; + -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in; + transition: opacity 2s ease-in-out .5s, color 4s ease-in; + } + `, + ); + + cssTest( + ` + .foo { + -webkit-transition-property: opacity; + -moz-transition-property: color; + transition-property: opacity, color; + -webkit-transition-duration: 2s; + -moz-transition-duration: 4s; + transition-duration: 2s, 4s; + -webkit-transition-timing-function: ease-in-out; + -moz-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out, ease-in; + -webkit-transition-delay: 500ms; + -moz-transition-delay: 0s; + transition-delay: 500ms, 0s; + } + `, + ` + .foo { + -webkit-transition-property: opacity; + -moz-transition-property: color; + transition-property: opacity, color; + -webkit-transition-duration: 2s; + -moz-transition-duration: 4s; + transition-duration: 2s, 4s; + -webkit-transition-timing-function: ease-in-out; + -moz-transition-timing-function: ease-in-out; + -webkit-transition-delay: .5s; + transition-timing-function: ease-in-out, ease-in; + -moz-transition-delay: 0s; + transition-delay: .5s, 0s; + } + `, + ); + + cssTest( + ` + .foo { + -webkit-transition-property: opacity; + transition-property: opacity, color; + -moz-transition-property: color; + -webkit-transition-duration: 2s; + transition-duration: 2s, 4s; + -moz-transition-duration: 4s; + -webkit-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out, ease-in; + -moz-transition-timing-function: ease-in-out; + -webkit-transition-delay: 500ms; + transition-delay: 500ms, 0s; + -moz-transition-delay: 0s; + } + `, + ` + .foo { + -webkit-transition-property: opacity; + transition-property: opacity, color; + -moz-transition-property: color; + -webkit-transition-duration: 2s; + transition-duration: 2s, 4s; + -moz-transition-duration: 4s; + -webkit-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out, ease-in; + -webkit-transition-delay: .5s; + -moz-transition-timing-function: ease-in-out; + transition-delay: .5s, 0s; + -moz-transition-delay: 0s; + } + `, + ); + + cssTest( + ` + .foo { + transition: opacity 2s; + -webkit-transition-duration: 2s; + } + `, + ` + .foo { + transition: opacity 2s; + -webkit-transition-duration: 2s; + } + `, + ); + + prefix_test( + ` + .foo { + transition-property: margin-inline-start; + } + `, + ` + .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition-property: margin-left; + } + + .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition-property: margin-left; + } + + .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition-property: margin-right; + } + + .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition-property: margin-right; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition-property: margin-inline-start, padding-inline-start; + } + `, + ` + .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition-property: margin-left, padding-left; + } + + .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition-property: margin-left, padding-left; + } + + .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition-property: margin-right, padding-right; + } + + .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition-property: margin-right, padding-right; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition-property: margin-inline-start, opacity, padding-inline-start, color; + } + `, + ` + .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition-property: margin-left, opacity, padding-left, color; + } + + .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition-property: margin-left, opacity, padding-left, color; + } + + .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition-property: margin-right, opacity, padding-right, color; + } + + .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition-property: margin-right, opacity, padding-right, color; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition-property: margin-block; + } + `, + ` + .foo { + transition-property: margin-top, margin-bottom; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition: margin-inline-start 2s; + } + `, + ` + .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition: margin-left 2s; + } + + .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition: margin-left 2s; + } + + .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition: margin-right 2s; + } + + .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition: margin-right 2s; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition: margin-inline-start 2s, padding-inline-start 2s; + } + `, + ` + .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition: margin-left 2s, padding-left 2s; + } + + .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + transition: margin-left 2s, padding-left 2s; + } + + .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition: margin-right 2s, padding-right 2s; + } + + .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + transition: margin-right 2s, padding-right 2s; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition: margin-block-start 2s; + } + `, + ` + .foo { + transition: margin-top 2s; + } + `, + { + safari: Some(8 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition: transform; + } + `, + ` + .foo { + -webkit-transition: -webkit-transform, transform; + transition: -webkit-transform, transform; + } + `, + { + safari: Some(6 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition: border-start-start-radius; + } + `, + ` + .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) { + -webkit-transition: -webkit-border-top-left-radius, border-top-left-radius; + transition: -webkit-border-top-left-radius, border-top-left-radius; + } + + .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) { + -webkit-transition: -webkit-border-top-right-radius, border-top-right-radius; + transition: -webkit-border-top-right-radius, border-top-right-radius; + } + `, + { + safari: Some(4 << 16), + }, + ); + + prefix_test( + ` + .foo { + transition: border-start-start-radius; + } + `, + ` + .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) { + transition: border-top-left-radius; + } + + .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) { + transition: border-top-right-radius; + } + `, + { + safari: Some(12 << 16), + }, + ); + + cssTest( + ` + .foo { + -webkit-transition: background 200ms; + -moz-transition: background 200ms; + transition: background 230ms; + } + `, + ` + .foo { + -webkit-transition: background .2s; + -moz-transition: background .2s; + transition: background .23s; + } + `, + ); + + prefix_test( + ` + .foo { + -webkit-transition: background 200ms; + -moz-transition: background 200ms; + transition: background 230ms; + } + `, + ` + .foo { + -webkit-transition: background .2s; + -moz-transition: background .2s; + transition: background .23s; + } + `, + { + chrome: Some(95 << 16), + }, + ); + }); + + describe("transform", () => { + minify_test(".foo { transform: translate(2px, 3px)", ".foo{transform:translate(2px,3px)}"); + minify_test(".foo { transform: translate(2px, 0px)", ".foo{transform:translate(2px)}"); + minify_test(".foo { transform: translate(0px, 2px)", ".foo{transform:translateY(2px)}"); + minify_test(".foo { transform: translateX(2px)", ".foo{transform:translate(2px)}"); + minify_test(".foo { transform: translateY(2px)", ".foo{transform:translateY(2px)}"); + minify_test(".foo { transform: translateZ(2px)", ".foo{transform:translateZ(2px)}"); + minify_test(".foo { transform: translate3d(2px, 3px, 4px)", ".foo{transform:translate3d(2px,3px,4px)}"); + minify_test(".foo { transform: translate3d(10%, 20%, 4px)", ".foo{transform:translate3d(10%,20%,4px)}"); + minify_test(".foo { transform: translate3d(2px, 0px, 0px)", ".foo{transform:translate(2px)}"); + minify_test(".foo { transform: translate3d(0px, 2px, 0px)", ".foo{transform:translateY(2px)}"); + minify_test(".foo { transform: translate3d(0px, 0px, 2px)", ".foo{transform:translateZ(2px)}"); + minify_test(".foo { transform: translate3d(2px, 3px, 0px)", ".foo{transform:translate(2px,3px)}"); + minify_test(".foo { transform: scale(2, 3)", ".foo{transform:scale(2,3)}"); + minify_test(".foo { transform: scale(10%, 20%)", ".foo{transform:scale(.1,.2)}"); + minify_test(".foo { transform: scale(2, 2)", ".foo{transform:scale(2)}"); + minify_test(".foo { transform: scale(2, 1)", ".foo{transform:scaleX(2)}"); + minify_test(".foo { transform: scale(1, 2)", ".foo{transform:scaleY(2)}"); + minify_test(".foo { transform: scaleX(2)", ".foo{transform:scaleX(2)}"); + minify_test(".foo { transform: scaleY(2)", ".foo{transform:scaleY(2)}"); + minify_test(".foo { transform: scaleZ(2)", ".foo{transform:scaleZ(2)}"); + minify_test(".foo { transform: scale3d(2, 3, 4)", ".foo{transform:scale3d(2,3,4)}"); + minify_test(".foo { transform: scale3d(2, 1, 1)", ".foo{transform:scaleX(2)}"); + minify_test(".foo { transform: scale3d(1, 2, 1)", ".foo{transform:scaleY(2)}"); + minify_test(".foo { transform: scale3d(1, 1, 2)", ".foo{transform:scaleZ(2)}"); + minify_test(".foo { transform: scale3d(2, 2, 1)", ".foo{transform:scale(2)}"); + minify_test(".foo { transform: rotate(20deg)", ".foo{transform:rotate(20deg)}"); + minify_test(".foo { transform: rotateX(20deg)", ".foo{transform:rotateX(20deg)}"); + minify_test(".foo { transform: rotateY(20deg)", ".foo{transform:rotateY(20deg)}"); + minify_test(".foo { transform: rotateZ(20deg)", ".foo{transform:rotate(20deg)}"); + minify_test(".foo { transform: rotate(360deg)", ".foo{transform:rotate(360deg)}"); + minify_test(".foo { transform: rotate3d(2, 3, 4, 20deg)", ".foo{transform:rotate3d(2,3,4,20deg)}"); + minify_test(".foo { transform: rotate3d(1, 0, 0, 20deg)", ".foo{transform:rotateX(20deg)}"); + minify_test(".foo { transform: rotate3d(0, 1, 0, 20deg)", ".foo{transform:rotateY(20deg)}"); + minify_test(".foo { transform: rotate3d(0, 0, 1, 20deg)", ".foo{transform:rotate(20deg)}"); + minify_test(".foo { transform: rotate(405deg)}", ".foo{transform:rotate(405deg)}"); + minify_test(".foo { transform: rotateX(405deg)}", ".foo{transform:rotateX(405deg)}"); + minify_test(".foo { transform: rotateY(405deg)}", ".foo{transform:rotateY(405deg)}"); + minify_test(".foo { transform: rotate(-200deg)}", ".foo{transform:rotate(-200deg)}"); + minify_test(".foo { transform: rotate(0)", ".foo{transform:rotate(0)}"); + minify_test(".foo { transform: rotate(0deg)", ".foo{transform:rotate(0)}"); + minify_test(".foo { transform: rotateX(-200deg)}", ".foo{transform:rotateX(-200deg)}"); + minify_test(".foo { transform: rotateY(-200deg)}", ".foo{transform:rotateY(-200deg)}"); + minify_test(".foo { transform: rotate3d(1, 1, 0, -200deg)", ".foo{transform:rotate3d(1,1,0,-200deg)}"); + minify_test(".foo { transform: skew(20deg)", ".foo{transform:skew(20deg)}"); + minify_test(".foo { transform: skew(20deg, 0deg)", ".foo{transform:skew(20deg)}"); + minify_test(".foo { transform: skew(0deg, 20deg)", ".foo{transform:skewY(20deg)}"); + minify_test(".foo { transform: skewX(20deg)", ".foo{transform:skew(20deg)}"); + minify_test(".foo { transform: skewY(20deg)", ".foo{transform:skewY(20deg)}"); + minify_test(".foo { transform: perspective(10px)", ".foo{transform:perspective(10px)}"); + minify_test(".foo { transform: matrix(1, 2, -1, 1, 80, 80)", ".foo{transform:matrix(1,2,-1,1,80,80)}"); + minify_test( + ".foo { transform: matrix3d(1, 0, 0, 0, 0, 1, 6, 0, 0, 0, 1, 0, 50, 100, 0, 1.1)", + ".foo{transform:matrix3d(1,0,0,0,0,1,6,0,0,0,1,0,50,100,0,1.1)}", + ); + // TODO: Re-enable with a better solution + // See: https://github.com/parcel-bundler/buncss/issues/288 + // minify_test( + // ".foo{transform:translate(100px,200px) rotate(45deg) skew(10deg) scale(2)}", + // ".foo{transform:matrix(1.41421,1.41421,-1.16485,1.66358,100,200)}", + // ); + // minify_test( + // ".foo{transform:translate(200px,300px) translate(100px,200px) scale(2)}", + // ".foo{transform:matrix(2,0,0,2,300,500)}", + // ); + minify_test( + ".foo{transform:translate(100px,200px) rotate(45deg)}", + ".foo{transform:translate(100px,200px)rotate(45deg)}", + ); + minify_test( + ".foo{transform:rotate3d(1, 1, 1, 45deg) translate3d(100px, 100px, 10px)}", + ".foo{transform:rotate3d(1,1,1,45deg)translate3d(100px,100px,10px)}", + ); + // TODO: Re-enable with a better solution + // See: https://github.com/parcel-bundler/buncss/issues/288 + // minify_test( + // ".foo{transform:translate3d(100px, 100px, 10px) skew(10deg) scale3d(2, 3, 4)}", + // ".foo{transform:matrix3d(2,0,0,0,.528981,3,0,0,0,0,4,0,100,100,10,1)}", + // ); + // minify_test( + // ".foo{transform:matrix3d(0.804737854124365, 0.5058793634016805, -0.31061721752604554, 0, -0.31061721752604554, 0.804737854124365, 0.5058793634016805, 0, 0.5058793634016805, -0.31061721752604554, 0.804737854124365, 0, 100, 100, 10, 1)}", + // ".foo{transform:translate3d(100px,100px,10px)rotate3d(1,1,1,45deg)}" + // ); + // minify_test( + // ".foo{transform:matrix3d(1, 0, 0, 0, 0, 0.7071067811865476, 0.7071067811865475, 0, 0, -0.7071067811865475, 0.7071067811865476, 0, 100, 100, 10, 1)}", + // ".foo{transform:translate3d(100px,100px,10px)rotateX(45deg)}" + // ); + // minify_test( + // ".foo{transform:translate3d(100px, 200px, 10px) translate(100px, 100px)}", + // ".foo{transform:translate3d(200px,300px,10px)}", + // ); + // minify_test( + // ".foo{transform:rotate(45deg) rotate(45deg)}", + // ".foo{transform:rotate(90deg)}", + // ); + // minify_test( + // ".foo{transform:matrix(0.7071067811865476, 0.7071067811865475, -0.7071067811865475, 0.7071067811865476, 100, 100)}", + // ".foo{transform:translate(100px,100px)rotate(45deg)}" + // ); + // minify_test( + // ".foo{transform:translateX(2in) translateX(50px)}", + // ".foo{transform:translate(242px)}", + // ); + minify_test(".foo{transform:translateX(calc(2in + 50px))}", ".foo{transform:translate(242px)}"); + minify_test(".foo{transform:translateX(50%)}", ".foo{transform:translate(50%)}"); + minify_test(".foo{transform:translateX(calc(50% - 100px + 20px))}", ".foo{transform:translate(calc(50% - 80px))}"); + minify_test(".foo{transform:rotate(calc(10deg + 20deg))}", ".foo{transform:rotate(30deg)}"); + minify_test(".foo{transform:rotate(calc(10deg + 0.349066rad))}", ".foo{transform:rotate(30deg)}"); + minify_test(".foo{transform:rotate(calc(10deg + 1.5turn))}", ".foo{transform:rotate(550deg)}"); + minify_test(".foo{transform:rotate(calc(10deg * 2))}", ".foo{transform:rotate(20deg)}"); + minify_test(".foo{transform:rotate(calc(-10deg * 2))}", ".foo{transform:rotate(-20deg)}"); + minify_test( + ".foo{transform:rotate(calc(10deg + var(--test)))}", + ".foo{transform:rotate(calc(10deg + var(--test)))}", + ); + minify_test(".foo { transform: scale(calc(10% + 20%))", ".foo{transform:scale(.3)}"); + minify_test(".foo { transform: scale(calc(.1 + .2))", ".foo{transform:scale(.3)}"); + + minify_test(".foo { -webkit-transform: scale(calc(10% + 20%))", ".foo{-webkit-transform:scale(.3)}"); + + minify_test(".foo { translate: 1px 2px 3px }", ".foo{translate:1px 2px 3px}"); + minify_test(".foo { translate: 1px 0px 0px }", ".foo{translate:1px}"); + minify_test(".foo { translate: 1px 2px 0px }", ".foo{translate:1px 2px}"); + minify_test(".foo { translate: 1px 0px 2px }", ".foo{translate:1px 0 2px}"); + minify_test(".foo { translate: none }", ".foo{translate:none}"); + minify_test(".foo { rotate: 10deg }", ".foo{rotate:10deg}"); + minify_test(".foo { rotate: z 10deg }", ".foo{rotate:10deg}"); + minify_test(".foo { rotate: 0 0 1 10deg }", ".foo{rotate:10deg}"); + minify_test(".foo { rotate: x 10deg }", ".foo{rotate:x 10deg}"); + minify_test(".foo { rotate: 1 0 0 10deg }", ".foo{rotate:x 10deg}"); + minify_test(".foo { rotate: y 10deg }", ".foo{rotate:y 10deg}"); + minify_test(".foo { rotate: 0 1 0 10deg }", ".foo{rotate:y 10deg}"); + minify_test(".foo { rotate: 1 1 1 10deg }", ".foo{rotate:1 1 1 10deg}"); + minify_test(".foo { rotate: 0 0 1 0deg }", ".foo{rotate:none}"); + minify_test(".foo { rotate: none }", ".foo{rotate:none}"); + minify_test(".foo { scale: 1 }", ".foo{scale:1}"); + minify_test(".foo { scale: 1 1 }", ".foo{scale:1}"); + minify_test(".foo { scale: 1 1 1 }", ".foo{scale:1}"); + minify_test(".foo { scale: none }", ".foo{scale:none}"); + minify_test(".foo { scale: 1 0 }", ".foo{scale:1 0}"); + minify_test(".foo { scale: 1 0 1 }", ".foo{scale:1 0}"); + minify_test(".foo { scale: 1 0 0 }", ".foo{scale:1 0 0}"); + + // TODO: Re-enable with a better solution + // See: https://github.com/parcel-bundler/buncss/issues/288 + // minify_test(".foo { transform: scale(3); scale: 0.5 }", ".foo{transform:scale(1.5)}"); + minify_test(".foo { scale: 0.5; transform: scale(3); }", ".foo{transform:scale(3)}"); + + prefix_test( + ` + .foo { + transform: scale(0.5); + } + `, + ` + .foo { + -webkit-transform: scale(.5); + -moz-transform: scale(.5); + transform: scale(.5); + } + `, + { + firefox: Some(6 << 16), + safari: Some(6 << 16), + }, + ); + + prefix_test( + ` + .foo { + transform: var(--transform); + } + `, + ` + .foo { + -webkit-transform: var(--transform); + -moz-transform: var(--transform); + transform: var(--transform); + } + `, + { + firefox: Some(6 << 16), + safari: Some(6 << 16), + }, + ); + + cssTest( + ` + .foo { + transform: translateX(-50%); + transform: translateX(20px); + } + `, + ` + .foo { + transform: translateX(20px); + } + `, + ); + }); + + describe("color-scheme", () => { + minify_test(".foo { color-scheme: normal; }", ".foo{color-scheme:normal}"); + minify_test(".foo { color-scheme: light; }", ".foo{color-scheme:light}"); + minify_test(".foo { color-scheme: dark; }", ".foo{color-scheme:dark}"); + minify_test(".foo { color-scheme: light dark; }", ".foo{color-scheme:light dark}"); + minify_test(".foo { color-scheme: dark light; }", ".foo{color-scheme:light dark}"); + minify_test(".foo { color-scheme: only light; }", ".foo{color-scheme:light only}"); + minify_test(".foo { color-scheme: only dark; }", ".foo{color-scheme:dark only}"); + minify_test(".foo { color-scheme: dark light only; }", ".foo{color-scheme:light dark only}"); + minify_test(".foo { color-scheme: foo bar light; }", ".foo{color-scheme:light}"); + minify_test(".foo { color-scheme: only foo dark bar; }", ".foo{color-scheme:dark only}"); + prefix_test( + ".foo { color-scheme: dark; }", + `.foo { + --buncss-light: ; + --buncss-dark: initial; + color-scheme: dark; + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color-scheme: light; }", + `.foo { + --buncss-light: initial; + --buncss-dark: ; + color-scheme: light; + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color-scheme: light dark; }", + `.foo { + --buncss-light: initial; + --buncss-dark: ; + color-scheme: light dark; + } + + @media (prefers-color-scheme: dark) { + .foo { + --buncss-light: ; + --buncss-dark: initial; + } + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color-scheme: light dark; }", + `.foo { + color-scheme: light dark; + } + `, + { firefox: Some(120 << 16) }, + ); + + minify_test(".foo { color: light-dark(yellow, red); }", ".foo{color:light-dark(#ff0,red)}"); + minify_test( + ".foo { color: light-dark(light-dark(yellow, red), light-dark(yellow, red)); }", + ".foo{color:light-dark(#ff0,red)}", + ); + minify_test( + ".foo { color: light-dark(rgb(0, 0, 255), hsl(120deg, 50%, 50%)); }", + ".foo{color:light-dark(#00f,#40bf40)}", + ); + prefix_test( + ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }", + `.foo { + color: var(--buncss-light, #7e250f) var(--buncss-dark, #c65d07); + color: var(--buncss-light, lab(29.2661% 38.2437 35.3889)) var(--buncss-dark, lab(52.2319% 40.1449 59.9171)); + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }", + `.foo { + color: light-dark(oklch(40% .126874 34.5686), oklab(59.686% .1009 .1192)); + } + `, + { firefox: Some(120 << 16) }, + ); + prefix_test( + ` + .foo { + box-shadow: + oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem, + currentColor 0 0.44rem 0.8rem -0.58rem; + } + `, + `.foo { + box-shadow: 0 .63rem .94rem -.19rem #ffffff80, 0 .44rem .8rem -.58rem; + box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem; + } + `, + { chrome: Some(95 << 16) }, + ); + prefix_test( + ` + .foo { + box-shadow: + oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem, + currentColor 0 0.44rem 0.8rem -0.58rem; + } + `, + `.foo { + box-shadow: 0 .63rem .94rem -.19rem color(display-p3 1 1 1 / .5), 0 .44rem .8rem -.58rem; + box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem; + } + `, + { safari: Some(14 << 16) }, + ); + + prefix_test( + ".foo { color: light-dark(var(--light), var(--dark)); }", + `.foo { + color: var(--buncss-light, var(--light)) var(--buncss-dark, var(--dark)); + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color: rgb(from light-dark(yellow, red) r g b / 10%); }", + `.foo { + color: var(--buncss-light, #ffff001a) var(--buncss-dark, #ff00001a); + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color: rgb(from light-dark(yellow, red) r g b / var(--alpha)); }", + `.foo { + color: var(--buncss-light, rgb(255 255 0 / var(--alpha))) var(--buncss-dark, rgb(255 0 0 / var(--alpha))); + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color: color(from light-dark(yellow, red) srgb r g b / 10%); }", + `.foo { + color: var(--buncss-light, #ffff001a) var(--buncss-dark, #ff00001a); + color: var(--buncss-light, color(srgb 1 1 0 / .1)) var(--buncss-dark, color(srgb 1 0 0 / .1)); + } + `, + { chrome: Some(90 << 16) }, + ); + prefix_test( + ".foo { color: color-mix(in srgb, light-dark(yellow, red), light-dark(red, pink)); }", + `.foo { + color: var(--buncss-light, #ff8000) var(--buncss-dark, #ff6066); + } + `, + { chrome: Some(90 << 16) }, + ); + }); }); diff --git a/test/js/bun/http/body-leak-test-fixture.ts b/test/js/bun/http/body-leak-test-fixture.ts index 5dbc7a1ea8a487..7c50ad88488cd4 100644 --- a/test/js/bun/http/body-leak-test-fixture.ts +++ b/test/js/bun/http/body-leak-test-fixture.ts @@ -11,6 +11,16 @@ const server = Bun.serve({ "Content-Type": "application/json", }, }); + } else if (url.endsWith("/heap-snapshot")) { + Bun.gc(true); + await Bun.sleep(10); + require("v8").writeHeapSnapshot("/tmp/heap.heapsnapshot"); + console.log("Wrote heap snapshot to /tmp/heap.heapsnapshot"); + return new Response(JSON.stringify(process.memoryUsage.rss()), { + headers: { + "Content-Type": "application/json", + }, + }); } if (url.endsWith("/json-buffering")) { await req.json(); @@ -44,3 +54,16 @@ const server = Bun.serve({ }); console.log(server.url.href); process?.send?.(server.url.href); + +if (!process.send) { + setInterval(() => { + Bun.gc(true); + const rss = (process.memoryUsage.rss() / 1024 / 1024) | 0; + console.log("RSS", rss, "MB"); + console.log("Active requests", server.pendingRequests); + + if (rss > 1024) { + require("v8").writeHeapSnapshot("/tmp/heap.heapsnapshot"); + } + }, 5000); +} diff --git a/test/js/bun/http/bun-serve-html-entry.test.ts b/test/js/bun/http/bun-serve-html-entry.test.ts new file mode 100644 index 00000000000000..250629671db154 --- /dev/null +++ b/test/js/bun/http/bun-serve-html-entry.test.ts @@ -0,0 +1,477 @@ +import type { Subprocess, Server } from "bun"; +import { describe, test, expect } from "bun:test"; +import { bunEnv, bunExe, tempDirWithFiles } from "harness"; +import { join } from "path"; + +async function getServerUrl(process: Subprocess) { + // Read the port number from stdout + const decoder = new TextDecoder(); + let serverUrl = ""; + let text = ""; + for await (const chunk of process.stdout) { + const textChunk = decoder.decode(chunk, { stream: true }); + text += textChunk; + console.log(textChunk); + + if (text.includes("http://")) { + serverUrl = text.trim(); + serverUrl = serverUrl.slice(serverUrl.indexOf("http://")); + + serverUrl = serverUrl.slice(0, serverUrl.indexOf("\n")); + if (URL.canParse(serverUrl)) { + break; + } + + serverUrl = serverUrl.slice(0, serverUrl.indexOf("/n")); + serverUrl = serverUrl.slice(0, serverUrl.lastIndexOf("/")); + serverUrl = serverUrl.trim(); + + if (URL.canParse(serverUrl)) { + break; + } + } + } + + if (!serverUrl) { + throw new Error("Could not find server URL in stdout"); + } + + return serverUrl; +} + +test("bun ./index.html", async () => { + const dir = tempDirWithFiles("html-entry-test", { + "index.html": /*html*/ ` + + + + HTML Entry Test + + + + +
    +

    Hello from Bun!

    + +
    + + + `, + "styles.css": /*css*/ ` + .container { + max-width: 800px; + margin: 2rem auto; + text-align: center; + font-family: system-ui, sans-serif; + } + + button { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.25rem; + border: 2px solid #000; + background: #fff; + cursor: pointer; + transition: all 0.2s; + } + + button:hover { + background: #000; + color: #fff; + } + `, + "app.js": /*js*/ ` + const button = document.getElementById('counter'); + let count = 0; + button.addEventListener('click', () => { + count++; + button.textContent = \`Click me: \${count}\`; + }); + `, + }); + + // Start the server by running bun with the HTML file + await using process = Bun.spawn({ + cmd: [bunExe(), "index.html", "--port=0"], + env: { + ...bunEnv, + NODE_ENV: undefined, + }, + cwd: dir, + stdout: "pipe", + }); + + const serverUrl = await getServerUrl(process); + + try { + // Make a request to the server using the detected URL + const response = await fetch(serverUrl); + expect(response.status).toBe(200); + expect(response.headers.get("content-type")).toContain("text/html"); + + const html = await response.text(); + + // Verify the HTML content + expect(html).toContain("HTML Entry Test"); + expect(html).toContain('
    '); + + // The bundler should have processed the CSS and JS files and injected them + expect(html).toMatch(//); + expect(html).toMatch(/ + + +
    +

    Welcome Home

    + About + +
    + + + `, + "about.html": /*html*/ ` + + + + About Page + + + + +
    +

    About Us

    + Home +

    This is the about page

    +
    + + + `, + "styles.css": /*css*/ ` + .container { + max-width: 800px; + margin: 2rem auto; + text-align: center; + font-family: system-ui, sans-serif; + } + a { + display: block; + margin: 1rem 0; + color: blue; + } + `, + "home.js": /*js*/ ` + const button = document.getElementById('counter'); + let count = 0; + button.addEventListener('click', () => { + count++; + button.textContent = \`Click me: \${count}\`; + }); + `, + "about.js": /*js*/ ` + const message = document.getElementById('message'); + message.textContent += " - Updated via JS"; + `, + }); + + // Start the server by running bun with multiple HTML files + await using process = Bun.spawn({ + cmd: [bunExe(), "index.html", "about.html", "--port=0"], + env: { + ...bunEnv, + NODE_ENV: undefined, + }, + cwd: dir, + stdout: "pipe", + }); + + const serverUrl = await getServerUrl(process); + + if (!serverUrl) { + throw new Error("Could not find server URL in stdout"); + } + + try { + // Test the home page + + const homeResponse = await fetch(serverUrl); + expect(homeResponse.status).toBe(200); + expect(homeResponse.headers.get("content-type")).toContain("text/html"); + + const homeHtml = await homeResponse.text(); + expect(homeHtml).toContain("Home Page"); + expect(homeHtml).toContain('About'); + expect(homeHtml).toMatch(/ + + + +
    +

    Welcome Home

    + +
    + + + `, + "about.html": /*html*/ ` + + + + About Page + + + + + +
    +

    About Us

    +

    This is the about page

    +
    + + + `, + "contact.html": /*html*/ ` + + + + Contact Page + + + + + +
    +

    Contact Us

    +
    + + +
    +
    + + + `, + "shared.css": /*css*/ ` + nav { + padding: 1rem; + background: #f0f0f0; + text-align: center; + } + nav a { + margin: 0 1rem; + color: blue; + } + .container { + max-width: 800px; + margin: 2rem auto; + text-align: center; + font-family: system-ui, sans-serif; + } + form { + display: flex; + flex-direction: column; + gap: 1rem; + max-width: 300px; + margin: 0 auto; + } + input, button { + padding: 0.5rem; + font-size: 1rem; + } + `, + "home.js": /*js*/ ` + const button = document.getElementById('counter'); + let count = 0; + button.addEventListener('click', () => { + count++; + button.textContent = \`Click me: \${count}\`; + }); + `, + "about.js": /*js*/ ` + const message = document.getElementById('message'); + message.textContent += " - Updated via JS"; + `, + "contact.js": /*js*/ ` + const form = document.getElementById('contact-form'); + form.addEventListener('submit', (e) => { + e.preventDefault(); + const input = form.querySelector('input'); + alert(\`Thanks for your message, \${input.value}!\`); + input.value = ''; + }); + `, + // Add a non-HTML file to verify it's not picked up + "README.md": "# Test Project\nThis file should be ignored by the glob.", + }); + + // Start the server using glob pattern + await using process = Bun.spawn({ + cmd: [bunExe(), "*.html", "--port=0"], + env: { + ...bunEnv, + NODE_ENV: undefined, + }, + cwd: dir, + stdout: "pipe", + }); + console.log({ cwd: dir }); + const serverUrl = await getServerUrl(process); + + try { + // Test all three pages are served + const pages = ["", "about", "contact"]; + const titles = ["Home Page", "About Page", "Contact Page"]; + + for (const [i, route] of pages.entries()) { + const response = await fetch(new URL(route, serverUrl).href); + expect(response.status).toBe(200); + expect(response.headers.get("content-type")).toContain("text/html"); + + const html = await response.text(); + expect(html).toContain(`${titles[i]}`); + expect(html).toMatch(/ + + + `, + "error.js": /*js*/ ` + throw new Error("Error on purpose"); + `, + }); + async function getServers() { + const path = join(dir, "index.html"); + + const { default: html } = await import(path); + let servers: Server[] = []; + for (let i = 0; i < 10; i++) { + servers.push( + Bun.serve({ + port: 0, + static: { + "/": html, + }, + development: true, + fetch(req) { + return new Response("Not found", { status: 404 }); + }, + }), + ); + } + + delete require.cache[path]; + + return servers; + } + + { + let servers = await getServers(); + Bun.gc(); + await Bun.sleep(1); + for (const server of servers) { + await server.stop(true); + } + servers = []; + Bun.gc(); + } + + Bun.gc(true); +}); + +test("wildcard static routes", async () => { + const dir = tempDirWithFiles("bun-serve-html-error-handling", { + "index.html": /*html*/ ` + + + + + + Error Page +

    Error Page

    + + + + `, + "error.js": /*js*/ ` + throw new Error("Error on purpose"); + `, + }); + const { default: html } = await import(join(dir, "index.html")); + for (let development of [true, false]) { + using server = Bun.serve({ + port: 0, + static: { + "/*": html, + }, + development, + fetch(req) { + return new Response("Not found", { status: 404 }); + }, + }); + + for (let url of [server.url, new URL("/potato", server.url)]) { + const response = await fetch(url); + expect(response.status).toBe(200); + expect(response.headers.get("content-type")).toContain("text/html"); + const text = await response.text(); + expect(text).toContain("Error Page"); + } + } +}); + +test("serve html with JSX runtime in development mode", async () => { + const dir = join(import.meta.dir, "jsx-runtime"); + const { default: html } = await import(join(dir, "index.html")); + + using server = Bun.serve({ + port: 0, + development: true, + static: { + "/": html, + }, + fetch(req) { + return new Response("Not found", { status: 404 }); + }, + }); + + const response = await fetch(server.url); + expect(response.status).toBe(200); + const htmlText = await response.text(); + const jsSrc = htmlText.match(/ + + +
    + + diff --git a/test/js/bun/http/req-url-leak-fixture.js b/test/js/bun/http/req-url-leak-fixture.js new file mode 100644 index 00000000000000..25dbbdf06173a3 --- /dev/null +++ b/test/js/bun/http/req-url-leak-fixture.js @@ -0,0 +1,26 @@ +let existingPromise = null; +const server = Bun.serve({ + port: 0, + async fetch(req) { + if (!existingPromise) { + existingPromise = Bun.sleep(0); + } + let waitedUpon = existingPromise; + await existingPromise; + if (existingPromise === waitedUpon) { + existingPromise = null; + } + return new Response(process.memoryUsage.rss().toString()); + }, +}); + +setInterval(() => { + console.log("RSS", (process.memoryUsage.rss() / 1024 / 1024) | 0); +}, 1000); +console.log("Server started on", server.url.href); + +if (process.channel) { + process.send({ + url: server.url.href, + }); +} diff --git a/test/js/bun/http/req-url-leak.test.ts b/test/js/bun/http/req-url-leak.test.ts new file mode 100644 index 00000000000000..2479c91b367eaa --- /dev/null +++ b/test/js/bun/http/req-url-leak.test.ts @@ -0,0 +1,47 @@ +import { test, expect } from "bun:test"; +import { bunExe, bunEnv } from "harness"; +import path from "path"; +test("req.url doesn't leak memory", async () => { + const { promise, resolve } = Promise.withResolvers(); + await using process = Bun.spawn({ + cmd: [bunExe(), path.join(import.meta.dir, "req-url-leak-fixture.js")], + env: bunEnv, + stdout: "inherit", + stderr: "inherit", + stdin: "inherit", + ipc(message, child) { + if (message.url) { + resolve(message.url); + } + }, + }); + + const baseURL = await promise; + + const url = new URL(Buffer.alloc(1024 * 15, "Z").toString(), baseURL); + + let maxRSS = 0; + + for (let i = 0; i < 512; i++) { + const batchSize = 64; + const promises = []; + for (let j = 0; j < batchSize; j++) { + promises.push( + fetch(url) + .then(r => r.text()) + .then(rssText => { + const rss = parseFloat(rssText); + if (Number.isSafeInteger(rss)) { + maxRSS = Math.max(maxRSS, rss); + } + }), + ); + } + await Promise.all(promises); + } + + console.log("RSS", maxRSS); + + // 557 MB on Bun 1.2 + expect(maxRSS).toBeLessThan(1024 * 1024 * 256); +}, 10_000); diff --git a/test/js/bun/http/serve-body-leak.test.ts b/test/js/bun/http/serve-body-leak.test.ts index 510a00a07853f1..2f9f38c66ab7d5 100644 --- a/test/js/bun/http/serve-body-leak.test.ts +++ b/test/js/bun/http/serve-body-leak.test.ts @@ -1,6 +1,6 @@ import type { Subprocess } from "bun"; import { afterEach, beforeEach, expect, it } from "bun:test"; -import { bunEnv, bunExe, isDebug, isFlaky, isLinux, isWindows } from "harness"; +import { bunEnv, bunExe, isCI, isDebug, isFlaky, isLinux, isWindows } from "harness"; import { join } from "path"; const payload = Buffer.alloc(512 * 1024, "1").toString("utf-8"); // decent size payload to test memory leak @@ -9,7 +9,22 @@ const totalCount = 10_000; const zeroCopyPayload = new Blob([payload]); const zeroCopyJSONPayload = new Blob([JSON.stringify({ bun: payload })]); +// let HARDCODED_URL = "http://localhost:52666/"; +let HARDCODED_URL = null; + async function getURL() { + if (HARDCODED_URL) { + const url = new URL(HARDCODED_URL); + await warmup(url); + return { + url, + process: { + [Symbol.asyncDispose]() { + return Promise.resolve(); + }, + }, + }; + } let defer = Promise.withResolvers(); const process = Bun.spawn([bunExe(), "--smol", join(import.meta.dirname, "body-leak-test-fixture.ts")], { env: bunEnv, @@ -153,13 +168,30 @@ for (const test_info of [ testName, async () => { const { url, process } = await getURL(); - await using processHandle = process; - const report = await calculateMemoryLeak(fn, url); - // peak memory is too high - expect(report.peak_memory).not.toBeGreaterThan(report.start_memory * 2.5); - // acceptable memory leak - expect(report.leak).toBeLessThanOrEqual(maxMemoryGrowth); - expect(report.end_memory).toBeLessThanOrEqual(512 * 1024 * 1024); + try { + const report = await calculateMemoryLeak(fn, url); + console.log(report); + // peak memory is too high + expect(report.peak_memory).not.toBeGreaterThan(report.start_memory * 2.5); + + // acceptable memory leak + expect(report.leak).toBeLessThanOrEqual(maxMemoryGrowth); + + expect(report.end_memory).toBeLessThanOrEqual(512 * 1024 * 1024); + } catch (e) { + if (!isCI && process.platform !== "win32") { + try { + await fetch(`${url.origin}/heap-snapshot`); + await Bun.sleep(10); + } catch (e) { + console.error(e); + } + } + + throw e; + } finally { + process.kill?.(); + } }, isDebug ? 60_000 : 40_000, ); diff --git a/test/js/bun/plugin/module-plugins.ts b/test/js/bun/plugin/module-plugins.ts index d6034c5dfcb096..965da7b3b7b25c 100644 --- a/test/js/bun/plugin/module-plugins.ts +++ b/test/js/bun/plugin/module-plugins.ts @@ -22,6 +22,25 @@ plugin({ }; }); + builder.module("my-virtual-module-with-__esModule", () => { + return { + exports: { + default: "world", + __esModule: true, + }, + loader: "object", + }; + }); + + builder.module("my-virtual-module-with-default", () => { + return { + exports: { + default: "world", + }, + loader: "object", + }; + }); + builder.onLoad({ filter: /.*/, namespace: "rejected-promise" }, async ({ path }) => { throw new Error("Rejected Promise"); }); diff --git a/test/js/bun/plugin/plugins.test.ts b/test/js/bun/plugin/plugins.test.ts index 2da1afa169f98d..a6f57b742548ec 100644 --- a/test/js/bun/plugin/plugins.test.ts +++ b/test/js/bun/plugin/plugins.test.ts @@ -484,3 +484,27 @@ describe("errors", () => { expect(text).toBe(result); }); }); + +it("require(...).default without __esModule", () => { + { + const { default: mod } = require("my-virtual-module-with-default"); + expect(mod).toBe("world"); + } +}); + +it("require(...) with __esModule", () => { + { + const mod = require("my-virtual-module-with-__esModule"); + expect(mod).toBe("world"); + } +}); + +it("import(...) with __esModule", async () => { + const { default: mod } = await import("my-virtual-module-with-__esModule"); + expect(mod).toBe("world"); +}); + +it("import(...) without __esModule", async () => { + const { default: mod } = await import("my-virtual-module-with-default"); + expect(mod).toBe("world"); +}); diff --git a/test/js/bun/resolve/resolve.test.ts b/test/js/bun/resolve/resolve.test.ts index 969449ffd01e82..3d7acb571eb7ee 100644 --- a/test/js/bun/resolve/resolve.test.ts +++ b/test/js/bun/resolve/resolve.test.ts @@ -1,8 +1,8 @@ -import { it, expect } from "bun:test"; +import { describe, it, expect } from "bun:test"; +import { pathToFileURL } from "bun"; import { mkdirSync, writeFileSync } from "fs"; import { join, sep } from "path"; -import { bunExe, bunEnv, tempDirWithFiles, isWindows } from "harness"; -import { pathToFileURL } from "bun"; +import { bunExe, bunEnv, tempDirWithFiles, joinP, isWindows } from "harness"; it("spawn test file", () => { writePackageJSONImportsFixture(); @@ -331,3 +331,104 @@ it.if(isWindows)("directory cache key computation", () => { expect(import(`\\\\Test\\doesnotexist.ts\\\\` as any)).rejects.toThrow(); expect(import(`\\\\\\Test\\doesnotexist.ts\\\\` as any)).rejects.toThrow(); }); + +describe("NODE_PATH test", () => { + const prepareTest = () => { + const tempDir = tempDirWithFiles("node_path", { + "modules/node_modules/node-path-test/index.js": "exports.testValue = 'NODE_PATH works';", + "modules/node_modules/node-path-test/package.json": JSON.stringify({ + name: "node-path-test", + version: "1.0.0", + description: "A node_path test module", + main: "index.js", + }), + "lib/node_modules/node-path-test/index.js": "exports.testValue = 'NODE_PATH from lib works';", + "lib/node_modules/node-path-test/package.json": JSON.stringify({ + name: "node-path-test", + version: "1.0.0", + description: "A node_path test module from lib", + main: "index.js", + }), + "test/index.js": "const { testValue } = require('node-path-test');\nconsole.log(testValue);", + }); + + const nodePath = joinP(tempDir, "modules/node_modules"); + const nodePathLib = joinP(tempDir, "lib/node_modules"); + const testDir = joinP(tempDir, "test"); + + const delimiter = isWindows ? ";" : ":"; + + return { + tempDir, + nodePath, + nodePathLib, + testDir, + delimiter, + }; + }; + + it("should resolve modules from NODE_PATH", () => { + const { nodePath, testDir } = prepareTest(); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), "--no-install", "index.js"], + env: { ...bunEnv, NODE_PATH: nodePath }, + cwd: testDir, + }); + + expect(exitCode).toBe(0); + expect(stdout.toString().trim()).toBe("NODE_PATH works"); + }); + + it("should resolve modules from NODE_PATH entries", () => { + const { nodePath, testDir, delimiter } = prepareTest(); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), "--no-install", "index.js"], + env: { ...bunEnv, NODE_PATH: [nodePath].join(delimiter) }, + cwd: testDir, + }); + + expect(exitCode).toBe(0); + expect(stdout.toString().trim()).toBe("NODE_PATH works"); + }); + + it("should resolve first matched module from NODE_PATH entries", () => { + const { nodePath, nodePathLib, testDir, delimiter } = prepareTest(); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), "--no-install", "index.js"], + env: { ...bunEnv, NODE_PATH: ["/a/path/not/exist", nodePathLib, nodePath].join(delimiter) }, + cwd: testDir, + }); + + expect(exitCode).toBe(0); + expect(stdout.toString().trim()).toBe("NODE_PATH from lib works"); + }); +}); + +it("can resolve with source directories that do not exist", () => { + // In Nuxt/Vite, the following call happens: + // `require("module").createRequire("file:///Users/clo/my-nuxt-app/@vue/server-renderer")("vue")` + // This seems to be a bug in their code, not using a concrete file path for + // this virtual module, such as 'node_modules/@vue/server-renderer/index.js', + // but the same exact resolution happens and succeeds in Node.js + const dir = tempDirWithFiles("resolve", { + "node_modules/vue/index.js": "export default 123;", + "test.js": ` + const { createRequire } = require('module'); + const assert = require('assert'); + const req = createRequire(import.meta.url + '/@vue/server-renderer'); + assert.strictEqual(req('vue').default, 123); + `, + }); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), "test.js"], + env: bunEnv, + cwd: dir, + stdio: ["ignore", "inherit", "inherit"], + }); + + expect(exitCode).toBe(0); +}); diff --git a/test/js/bun/s3/s3.test.ts b/test/js/bun/s3/s3.test.ts index a1c280b2666918..d779a6f6fd3a3c 100644 --- a/test/js/bun/s3/s3.test.ts +++ b/test/js/bun/s3/s3.test.ts @@ -5,7 +5,7 @@ import { S3Client, s3 as defaultS3, file, which } from "bun"; const s3 = (...args) => defaultS3.file(...args); const S3 = (...args) => new S3Client(...args); import child_process from "child_process"; -import type { S3Options } from "bun"; +import type { S3File, S3Options } from "bun"; import path from "path"; const dockerCLI = which("docker") as string; @@ -33,7 +33,6 @@ const allCredentials = [ ]; if (isDockerEnabled()) { - const minio_dir = tempDirWithFiles("minio", {}); const result = child_process.spawnSync( "docker", [ @@ -49,8 +48,8 @@ if (isDockerEnabled()) { "MINIO_ROOT_USER=minioadmin", "-e", "MINIO_ROOT_PASSWORD=minioadmin", - "-v", - `${minio_dir}:/data`, + "--mount", + "type=tmpfs,destination=/data", "minio/minio", "server", "--console-address", @@ -93,10 +92,7 @@ for (let credentials of allCredentials) { const S3Bucket = credentials.bucket; function makePayLoadFrom(text: string, size: number): string { - while (Buffer.byteLength(text) < size) { - text += text; - } - return text.slice(0, size); + return Buffer.alloc(size, text).toString(); } // 10 MiB big enough to Multipart upload in more than one part @@ -325,6 +321,37 @@ for (let credentials of allCredentials) { expect(await s3File.text()).toBe(bigPayload); } }, 10_000); + + for (let queueSize of [1, 5, 7, 10, 20]) { + for (let payloadQuantity of [1, 5, 7, 10, 20]) { + for (let partSize of [5, 7, 10]) { + // the larger payload causes OOM in CI. + for (let payload of [bigishPayload]) { + // lets skip tests with more than 10 parts on cloud providers + it.skipIf(credentials.service !== "MinIO")( + `should be able to upload large files using writer() in multiple parts with partSize=${partSize} queueSize=${queueSize} payloadQuantity=${payloadQuantity} payloadSize=${payload.length * payloadQuantity}`, + async () => { + { + const s3File = bucket.file(tmp_filename, options); + const writer = s3File.writer({ + queueSize, + partSize: partSize * 1024 * 1024, + }); + for (let i = 0; i < payloadQuantity; i++) { + writer.write(payload); + } + await writer.end(); + const stat = await s3File.stat(); + expect(stat.size).toBe(Buffer.byteLength(payload) * payloadQuantity); + s3File.delete(); + } + }, + 30_000, + ); + } + } + } + } }); }); @@ -399,6 +426,7 @@ for (let credentials of allCredentials) { await writer.end(); expect(await s3file.text()).toBe(mediumPayload.repeat(2)); + s3file.delete(); }); it("should be able to upload large files in one go using Bun.write", async () => { { @@ -414,6 +442,7 @@ for (let credentials of allCredentials) { await s3File.write(bigPayload); expect(s3File.size).toBeNaN(); expect(await s3File.text()).toBe(bigPayload); + s3File.delete(); } }, 10_000); }); @@ -504,6 +533,7 @@ for (let credentials of allCredentials) { expect(stat.lastModified).toBeDefined(); expect(await s3file.text()).toBe(bigPayload); + s3file.delete(); } }, 10_000); @@ -518,6 +548,7 @@ for (let credentials of allCredentials) { expect(stat.lastModified).toBeDefined(); expect(await s3File.text()).toBe(bigPayload); + s3File.delete(); } }, 10_000); @@ -545,6 +576,7 @@ for (let credentials of allCredentials) { } expect(bytes).toBe(10); expect(Buffer.concat(chunks)).toEqual(Buffer.from("Hello Bun!")); + s3file.delete(); }); it("should work with large files ", async () => { const s3file = s3(tmp_filename + "-readable-stream-big", options); @@ -559,8 +591,18 @@ for (let credentials of allCredentials) { bytes += value?.length ?? 0; if (value) chunks.push(value as Buffer); } - expect(bytes).toBe(Buffer.byteLength(bigishPayload)); - expect(Buffer.concat(chunks).toString()).toBe(bigishPayload); + + const bigishPayloadString = Buffer.concat(chunks).toString(); + expect(bigishPayload.length).toBe(bigishPayloadString.length); + + // if this test fails, then we want to avoid printing megabytes to stderr. + + if (bigishPayloadString !== bigishPayload) { + const SHA1 = Bun.SHA1.hash(bigishPayloadString, "hex"); + const SHA1_2 = Bun.SHA1.hash(bigishPayload, "hex"); + expect(SHA1).toBe(SHA1_2); + } + s3file.delete(); }, 30_000); }); }); @@ -591,33 +633,39 @@ for (let credentials of allCredentials) { await s3file.unlink(); expect().pass(); }); - it("should allow starting with slashs and backslashes", async () => { + it("should allow starting with forward slash", async () => { const options = { ...s3Options, bucket: S3Bucket }; - { - const s3file = s3(`/${randomUUID()}test.txt`, options); - await s3file.write("Hello Bun!"); - await s3file.unlink(); - } - { - const s3file = s3(`\\${randomUUID()}test.txt`, options); - await s3file.write("Hello Bun!"); - await s3file.unlink(); - } + const s3file = s3(`/${randomUUID()}test.txt`, options); + await s3file.write("Hello Bun!"); + await s3file.exists(); + await s3file.unlink(); expect().pass(); }); - it("should allow ending with slashs and backslashes", async () => { + it("should allow starting with backslash", async () => { const options = { ...s3Options, bucket: S3Bucket }; - { - const s3file = s3(`${randomUUID()}/`, options); - await s3file.write("Hello Bun!"); - await s3file.unlink(); - } - { - const s3file = s3(`${randomUUID()}\\`, options); - await s3file.write("Hello Bun!"); - await s3file.unlink(); - } + const s3file = s3(`\\${randomUUID()}test.txt`, options); + await s3file.write("Hello Bun!"); + await s3file.exists(); + await s3file.unlink(); + expect().pass(); + }); + + it("should allow ending with forward slash", async () => { + const options = { ...s3Options, bucket: S3Bucket }; + const s3file = s3(`${randomUUID()}/`, options); + await s3file.write("Hello Bun!"); + await s3file.exists(); + await s3file.unlink(); + expect().pass(); + }); + + it("should allow ending with backslash", async () => { + const options = { ...s3Options, bucket: S3Bucket }; + const s3file = s3(`${randomUUID()}\\`, options); + await s3file.write("Hello Bun!"); + await s3file.exists(); + await s3file.unlink(); expect().pass(); }); }); diff --git a/test/js/bun/test/snapshot-tests/snapshots/__snapshots__/snapshot.test.ts.snap b/test/js/bun/test/snapshot-tests/snapshots/__snapshots__/snapshot.test.ts.snap index 5effa6968c9223..34d5ce7c3295b9 100644 --- a/test/js/bun/test/snapshot-tests/snapshots/__snapshots__/snapshot.test.ts.snap +++ b/test/js/bun/test/snapshot-tests/snapshots/__snapshots__/snapshot.test.ts.snap @@ -607,3 +607,19 @@ exports[`snapshot numbering 4`] = `"snap"`; exports[`snapshot numbering 6`] = `"hello"`; exports[`snapshot numbering: hinted 1`] = `"hello"`; + +exports[`indented inline snapshots 4`] = ` +"\x1B[2mexpect(\x1B[0m\x1B[31mreceived\x1B[0m\x1B[2m).\x1B[0mtoMatchInlineSnapshot\x1B[2m(\x1B[0m\x1B[32mexpected\x1B[0m\x1B[2m)\x1B[0m + +Expected: \x1B[2m +\x1B[0m\x1B[32m \x1B[0m\x1B[2m{ + \x1B[0m\x1B[32m \x1B[0m\x1B[2m"a": 2, +\x1B[0m\x1B[32m \x1B[0m\x1B[2m} +\x1B[0m +Received: \x1B[2m +\x1B[0m\x1B[2m{ + \x1B[0m\x1B[2m"a": 2, +\x1B[0m\x1B[2m} +\x1B[0m +" +`; diff --git a/test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts b/test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts index d211fd4c19ebb3..2c2bc51d87dab2 100644 --- a/test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts +++ b/test/js/bun/test/snapshot-tests/snapshots/snapshot.test.ts @@ -410,6 +410,13 @@ class InlineSnapshotTester { cb((a, b, c) => c), ); } + testUpdateOnly(cb: (v: (b: string, c: string) => string) => string): void { + this.testInternal( + true, + cb((b, c) => b), + cb((b, c) => c), + ); + } testInternal(use_update: boolean, before_value: string, after_value: string): void { const thefile = this.tmpfile(before_value); @@ -513,6 +520,7 @@ describe("inline snapshots", () => { }); test("inline snapshot update cases", () => { tester.test( + // prettier-ignore v => /*js*/ ` test("cases", () => { expect("1").toMatchInlineSnapshot(${v("", bad, '`"1"`')}); @@ -534,19 +542,72 @@ describe("inline snapshots", () => { ${v("", bad, '`"12"`')})\r ; expect("13").toMatchInlineSnapshot(${v("", bad, '`"13"`')}); expect("14").toMatchInlineSnapshot(${v("", bad, '`"14"`')}); expect("15").toMatchInlineSnapshot(${v("", bad, '`"15"`')}); - expect({a: new Date()}).toMatchInlineSnapshot({a: expect.any(Date)}${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()}).toMatchInlineSnapshot({a: expect.any(Date)}${v(",", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()}).toMatchInlineSnapshot({a: expect.any(Date)\n}${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()}).\ntoMatchInlineSnapshot({a: expect.any(Date)\n}${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()})\n.\ntoMatchInlineSnapshot({a: expect.any(Date)\n}${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()})\n.\ntoMatchInlineSnapshot({a: \nexpect.any(Date)\n}${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()})\n.\ntoMatchInlineSnapshot({a: \nexpect.any(\nDate)\n}${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()}).toMatchInlineSnapshot( {a: expect.any(Date)} ${v("", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect({a: new Date()}).toMatchInlineSnapshot( {a: expect.any(Date)} ${v(",", ', "bad"', ', `\n{\n "a": Any,\n}\n`')}); - expect("😊").toMatchInlineSnapshot(${v("", bad, '`"😊"`')}); - expect("\\r").toMatchInlineSnapshot(${v("", bad, '`\n"\n"\n`')}); - expect("\\r\\n").toMatchInlineSnapshot(${v("", bad, '`\n"\n"\n`')}); - expect("\\n").toMatchInlineSnapshot(${v("", bad, '`\n"\n"\n`')}); + expect({a: new Date()}).toMatchInlineSnapshot({a: expect.any(Date)}${v("", `, "bad"`, `, \` + { + "a": Any, + } + \``)}); + expect({a: new Date()}).toMatchInlineSnapshot({a: expect.any(Date)}${v(",", `, "bad"`, `, \` + { + "a": Any, + } + \``)}); + expect({a: new Date()}).toMatchInlineSnapshot({a: expect.any(Date) +}${v("", `, "bad"`, `, \` + { + "a": Any, + } +\``)}); + expect({a: new Date()}).\ntoMatchInlineSnapshot({a: expect.any(Date) +}${v("", `, "bad"`, `, \` + { + "a": Any, + } +\``)}); + expect({a: new Date()})\n.\ntoMatchInlineSnapshot({a: expect.any(Date) +}${v("", `, "bad"`, `, \` + { + "a": Any, + } +\``)}); + expect({a: new Date()})\n.\ntoMatchInlineSnapshot({a: +expect.any(Date) +}${v("", `, "bad"`, `, \` + { + "a": Any, + } +\``)}); + expect({a: new Date()})\n.\ntoMatchInlineSnapshot({a: +expect.any( +Date) +}${v("", `, "bad"`, `, \` + { + "a": Any, + } +\``)}); + expect({a: new Date()}).toMatchInlineSnapshot( {a: expect.any(Date)} ${v("", `, "bad"`, `, \` + { + "a": Any, + } + \``)}); + expect({a: new Date()}).toMatchInlineSnapshot( {a: expect.any(Date)} ${v(",", `, "bad"`, `, \` + { + "a": Any, + } + \``)}); + expect("😊").toMatchInlineSnapshot(${v("", bad, `\`"😊"\``)}); + expect("\\r").toMatchInlineSnapshot(${v("", bad, `\` + " + " + \``)}); + expect("\\r\\n").toMatchInlineSnapshot(${v("", bad, `\` + " + " + \``)}); + expect("\\n").toMatchInlineSnapshot(${v("", bad, `\` + " + " + \``)}); }); `, ); @@ -741,6 +802,60 @@ describe("inline snapshots", () => { `, ); }); + it("indentation", () => { + tester.test( + // prettier-ignore + v => /*js*/ ` + test("cases", () => { + expect("abc\\n\\ndef").toMatchInlineSnapshot(${v("", `"hello"`, `\` + "abc + + def" + \``)}); + expect("from indented to dedented").toMatchInlineSnapshot(${v("", `\` + "abc + + def" + \``, `\`"from indented to dedented"\``)}); + }); + `, + ); + }); + it("preserve existing indentation", () => { + tester.testUpdateOnly( + // prettier-ignore + v => /*js*/ ` + test("cases", () => { + expect("keeps the same\\n\\nindentation").toMatchInlineSnapshot(${v(`\` + "weird existing + indentation" + \``, `\` + "keeps the same + + indentation" + \``)}); + }); + `, + ); + }); +}); +test("indented inline snapshots", () => { + expect("a\nb").toMatchInlineSnapshot(` + "a + b" +`); + expect({ a: 2 }).toMatchInlineSnapshot(` + { + "a": 2, + } + `); + expect(() => { + expect({ a: 2 }).toMatchInlineSnapshot(` + { + "a": 2, + } +`); + }).toThrowErrorMatchingSnapshot(); }); test("error snapshots", () => { @@ -756,6 +871,14 @@ test("error snapshots", () => { expect(() => { throw undefined; // this one doesn't work in jest because it doesn't think the function threw }).toThrowErrorMatchingInlineSnapshot(`undefined`); + expect(() => { + expect(() => {}).toThrowErrorMatchingInlineSnapshot(`undefined`); + }).toThrowErrorMatchingInlineSnapshot(` +"\x1B[2mexpect(\x1B[0m\x1B[31mreceived\x1B[0m\x1B[2m).\x1B[0mtoThrowErrorMatchingInlineSnapshot\x1B[2m(\x1B[0m\x1B[2m)\x1B[0m + +\x1B[1mMatcher error\x1B[0m: Received function did not throw +" +`); }); test("error inline snapshots", () => { expect(() => { diff --git a/test/js/bun/util/BunObject.test.ts b/test/js/bun/util/BunObject.test.ts new file mode 100644 index 00000000000000..9b58ef98dd6c11 --- /dev/null +++ b/test/js/bun/util/BunObject.test.ts @@ -0,0 +1,21 @@ +import { expect, test } from "bun:test"; + +test("require('bun')", () => { + const str = eval("'bun'"); + expect(require(str)).toBe(Bun); +}); + +test("await import('bun')", async () => { + const str = eval("'bun'"); + const BunESM = await import(str); + + // console.log it so that we iterate through all the fields and crash if it's + // in an unexpected state. + console.log(BunESM); + + for (let property in Bun) { + expect(BunESM).toHaveProperty(property); + expect(BunESM[property]).toBe(Bun[property]); + } + expect(BunESM.default).toBe(Bun); +}); diff --git a/test/js/bun/util/bun-file.test.ts b/test/js/bun/util/bun-file.test.ts new file mode 100644 index 00000000000000..33976872d1c79e --- /dev/null +++ b/test/js/bun/util/bun-file.test.ts @@ -0,0 +1,23 @@ +import { test, expect } from "bun:test"; +import { tmpdirSync } from "harness"; +import { join } from "path"; + +test("delete() and stat() should work with unicode paths", async () => { + const testDir = tmpdirSync(); + const filename = join(testDir, "🌟.txt"); + + expect(async () => { + await Bun.file(filename).delete(); + }).toThrow(`ENOENT: no such file or directory, unlink '${filename}'`); + + expect(async () => { + await Bun.file(filename).stat(); + }).toThrow(`ENOENT: no such file or directory, stat '${filename}'`); + + await Bun.write(filename, "HI"); + + expect(await Bun.file(filename).stat()).toMatchObject({ size: 2 }); + expect(await Bun.file(filename).delete()).toBe(undefined); + + expect(await Bun.file(filename).exists()).toBe(false); +}); diff --git a/test/js/bun/util/password.test.ts b/test/js/bun/util/password.test.ts index f838ad3a485406..0d8fd5cc25f9cd 100644 --- a/test/js/bun/util/password.test.ts +++ b/test/js/bun/util/password.test.ts @@ -217,7 +217,7 @@ for (let algorithmValue of algorithms) { expect(verifySync(input + "\0", hashed)).toBeFalse(); }); - test("password", async () => { + describe("password", async () => { async function runSlowTest(algorithm = algorithmValue as any) { const hashed = await password.hash(input, algorithm); const prefix = "$" + algorithm; @@ -228,12 +228,13 @@ for (let algorithmValue of algorithms) { } async function runSlowTestWithOptions(algorithmLabel: any) { - const algorithm = { algorithm: algorithmLabel, timeCost: 5, memoryCost: 4 }; + const algorithm = { algorithm: algorithmLabel, timeCost: 5, memoryCost: 8 }; const hashed = await password.hash(input, algorithm); const prefix = "$" + algorithmLabel; expect(hashed).toStartWith(prefix); expect(hashed).toContain("t=5"); - expect(hashed).toContain("m=4"); + expect(hashed).toContain("m=8"); + expect(hashed).toContain("p=1"); expect(await password.verify(input, hashed, algorithmLabel)).toBeTrue(); expect(() => password.verify(hashed, input, algorithmLabel)).toThrow(); expect(await password.verify(input + "\0", hashed, algorithmLabel)).toBeFalse(); @@ -252,7 +253,12 @@ for (let algorithmValue of algorithms) { if (algorithmValue === defaultAlgorithm) { // these tests are very slow // run the hashing tests in parallel - await Promise.all([...argons.map(runSlowTest), ...argons.map(runSlowTestWithOptions)]); + for (const a of argons) { + test(`${a}`, async () => { + await runSlowTest(a); + await runSlowTestWithOptions(a); + }) + } return; } @@ -265,9 +271,14 @@ for (let algorithmValue of algorithms) { } if (algorithmValue === "bcrypt") { - await Promise.all([defaultTest(), runSlowBCryptTest()]); + test("bcrypt", async () => { + await defaultTest(); + await runSlowBCryptTest(); + }); } else { - await defaultTest(); + test("default", async () => { + await defaultTest(); + }); } }); }); diff --git a/test/js/node/async_hooks/AsyncLocalStorage.test.ts b/test/js/node/async_hooks/AsyncLocalStorage.test.ts index ffa8856d908220..0c28f96e7c81a5 100644 --- a/test/js/node/async_hooks/AsyncLocalStorage.test.ts +++ b/test/js/node/async_hooks/AsyncLocalStorage.test.ts @@ -545,8 +545,9 @@ describe("async context passes through", () => { const s = new AsyncLocalStorage(); let a = undefined; await s.run("value", async () => { - Bun.build({ + return Bun.build({ entrypoints: [import.meta.path], + target: "bun", plugins: [ { name: "test", diff --git a/test/js/node/buffer.test.js b/test/js/node/buffer.test.js index 08830c4bfc8736..dbb059883fc3c6 100644 --- a/test/js/node/buffer.test.js +++ b/test/js/node/buffer.test.js @@ -1205,7 +1205,7 @@ for (let withOverridenBufferWrite of [false, true]) { it("toLocaleString()", () => { const buf = Buffer.from("test"); expect(buf.toLocaleString()).toBe(buf.toString()); - // expect(Buffer.prototype.toLocaleString).toBe(Buffer.prototype.toString); + expect(Buffer.prototype.toLocaleString).toBe(Buffer.prototype.toString); }); it("alloc() should throw on invalid data", () => { diff --git a/test/js/node/child_process/child-process-stdio.test.js b/test/js/node/child_process/child-process-stdio.test.js index 59865a533f40a5..8b133ec15081d9 100644 --- a/test/js/node/child_process/child-process-stdio.test.js +++ b/test/js/node/child_process/child-process-stdio.test.js @@ -25,7 +25,7 @@ describe("process.stdout", () => { describe("process.stdin", () => { it("should allow us to read from stdin in readable mode", done => { - const input = "hello\n"; + const input = "hello there\n"; // Child should read from stdin and write it back const child = spawn(bunExe(), [CHILD_PROCESS_FILE, "STDIN", "READABLE"], { env: bunEnv, diff --git a/test/js/node/child_process/child_process-node.test.js b/test/js/node/child_process/child_process-node.test.js index 710eb5be676ac8..c4ca225ebceb77 100644 --- a/test/js/node/child_process/child_process-node.test.js +++ b/test/js/node/child_process/child_process-node.test.js @@ -657,7 +657,7 @@ describe("fork", () => { code: "ERR_INVALID_ARG_TYPE", name: "TypeError", message: expect.stringContaining( - `The "modulePath" argument must be of type string, Buffer or URL. Received `, + `The "modulePath" argument must be of type string, Buffer, or URL. Received `, ), }), ); diff --git a/test/js/node/crypto/crypto.key-objects.test.ts b/test/js/node/crypto/crypto.key-objects.test.ts index 3f9dac8ed4f29e..5c6cc1f902d338 100644 --- a/test/js/node/crypto/crypto.key-objects.test.ts +++ b/test/js/node/crypto/crypto.key-objects.test.ts @@ -390,8 +390,8 @@ describe("crypto.KeyObjects", () => { }, ].forEach(info => { const keyType = info.keyType; - // X25519 implementation is incomplete, Ed448 and X448 are not supported yet - const test = keyType === "ed25519" ? it : it.skip; + // Ed448 and X448 are not supported yet + const test = keyType === "x448" || keyType === "ed448" ? it.skip : it; let privateKey: KeyObject; test(`${keyType} from Buffer should work`, async () => { const key = createPrivateKey(info.private); @@ -677,8 +677,7 @@ describe("crypto.KeyObjects", () => { }); ["ed25519", "x25519"].forEach(keyType => { - const test = keyType === "ed25519" ? it : it.skip; - test(`${keyType} equals should work`, async () => { + it(`${keyType} equals should work`, async () => { const first = generateKeyPairSync(keyType); const second = generateKeyPairSync(keyType); @@ -824,7 +823,7 @@ describe("crypto.KeyObjects", () => { describe("Test async elliptic curve key generation with 'jwk' encoding", () => { ["ed25519", "ed448", "x25519", "x448"].forEach(type => { - const test = type === "ed25519" ? it : it.skip; + const test = type === "x448" || type === "ed448" ? it.skip : it; test(`should work with ${type}`, async () => { const { promise, resolve, reject } = Promise.withResolvers(); generateKeyPair( @@ -1171,7 +1170,7 @@ describe("crypto.KeyObjects", () => { describe("Test sync elliptic curve key generation with 'jwk' encoding", () => { ["ed25519", "ed448", "x25519", "x448"].forEach(type => { - const test = type === "ed25519" ? it : it.skip; + const test = type === "x448" || type === "ed448" ? it.skip : it; test(`should work with ${type}`, async () => { const { publicKey, privateKey } = generateKeyPairSync(type, { publicKeyEncoding: { @@ -1665,10 +1664,13 @@ test("Ed25519 should work", async () => { expect(publicKey.type).toBe("public"); expect(publicKey.asymmetricKeyType).toBe("ed25519"); - expect(publicKey.asymmetricKeyDetails).toEqual({ namedCurve: "Ed25519" }); + expect(privateKey.type).toBe("private"); expect(privateKey.asymmetricKeyType).toBe("ed25519"); - expect(privateKey.asymmetricKeyDetails).toEqual({ namedCurve: "Ed25519" }); + + // TODO: this should be an empty object. Node doesn't always include the details. + expect(privateKey.asymmetricKeyDetails).toBeObject(); + expect(publicKey.asymmetricKeyDetails).toBeObject(); { const signature = sign(undefined, Buffer.from("foo"), privateKey); diff --git a/test/js/node/crypto/node-crypto.test.js b/test/js/node/crypto/node-crypto.test.js index af41d614071e4e..681ef229105c09 100644 --- a/test/js/node/crypto/node-crypto.test.js +++ b/test/js/node/crypto/node-crypto.test.js @@ -536,3 +536,106 @@ it("createDecipheriv should validate iv and password", () => { expect(() => crypto.createDecipheriv("aes-128-cbc", key).setAutoPadding(false)).toThrow(); expect(() => crypto.createDecipheriv("aes-128-cbc", key, Buffer.alloc(16)).setAutoPadding(false)).not.toThrow(); }); + +it("x25519", () => { + // Generate Alice's keys + const alice = crypto.generateKeyPairSync("x25519", { + publicKeyEncoding: { + type: "spki", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "der", + }, + }); + + // Generate Bob's keys + const bob = crypto.generateKeyPairSync("x25519", { + publicKeyEncoding: { + type: "spki", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "der", + }, + }); + + // Convert keys to KeyObjects before DH computation + const alicePrivateKey = crypto.createPrivateKey({ + key: alice.privateKey, + format: "der", + type: "pkcs8", + }); + + const bobPublicKey = crypto.createPublicKey({ + key: bob.publicKey, + format: "der", + type: "spki", + }); + + const bobPrivateKey = crypto.createPrivateKey({ + key: bob.privateKey, + format: "der", + type: "pkcs8", + }); + + const alicePublicKey = crypto.createPublicKey({ + key: alice.publicKey, + format: "der", + type: "spki", + }); + + // Compute shared secrets using KeyObjects + const aliceSecret = crypto.diffieHellman({ + privateKey: alicePrivateKey, + publicKey: bobPublicKey, + }); + + const bobSecret = crypto.diffieHellman({ + privateKey: bobPrivateKey, + publicKey: alicePublicKey, + }); + + // Verify both parties computed the same secret + expect(aliceSecret).toEqual(bobSecret); + expect(aliceSecret.length).toBe(32); + + // Verify valid key generation + expect(() => { + crypto.generateKeyPairSync("x25519", { + publicKeyEncoding: { + type: "spki", + format: "der", + }, + privateKeyEncoding: { + type: "pkcs8", + format: "der", + }, + }); + }).not.toThrow(); + + // Test invalid keys - need to create proper KeyObjects even for invalid cases + expect(() => { + crypto.diffieHellman({ + privateKey: crypto.createPrivateKey({ + key: Buffer.from("invalid"), + format: "der", + type: "pkcs8", + }), + publicKey: bobPublicKey, + }); + }).toThrow(); + + expect(() => { + crypto.diffieHellman({ + privateKey: bobPrivateKey, + publicKey: crypto.createPublicKey({ + key: Buffer.from("invalid"), + format: "der", + type: "spki", + }), + }); + }).toThrow(); +}); diff --git a/test/js/node/fs/abort-signal-leak-read-write-file-fixture.ts b/test/js/node/fs/abort-signal-leak-read-write-file-fixture.ts new file mode 100644 index 00000000000000..891591e408ad95 --- /dev/null +++ b/test/js/node/fs/abort-signal-leak-read-write-file-fixture.ts @@ -0,0 +1,38 @@ +import fs from "fs"; +import { join } from "path"; +import { tmpdirSync } from "harness"; +import { heapStats } from "bun:jsc"; + +const tmpdir = tmpdirSync(); + +for (let i = 0; i < 100_000; i++) { + try { + const signal = AbortSignal.abort(); + await fs.promises.readFile("blah", { signal }); + } catch (e) {} + try { + const signal = AbortSignal.abort(); + await fs.promises.writeFile("blah", "blah", { signal }); + } catch (e) {} + + // aborting later does not leak in writeFile + const controller = new AbortController(); + const signal = controller.signal; + const prom = fs.promises.writeFile(join(tmpdir, "blah"), "blah", { signal }); + process.nextTick(() => controller.abort()); + try { + await prom; + } catch (e) {} +} + +Bun.gc(true); + +const numAbortSignalObjects = heapStats().objectTypeCounts.AbortSignal; +if (numAbortSignalObjects > 10) { + throw new Error(`AbortSignal objects > 10, received ${numAbortSignalObjects}`); +} + +const rss = (process.memoryUsage().rss / 1024 / 1024) | 0; +if (rss > 170) { + throw new Error(`Memory leak detected: ${rss} MB, expected < 170 MB`); +} diff --git a/test/js/node/fs/abort-signal-leak-read-write-file.test.ts b/test/js/node/fs/abort-signal-leak-read-write-file.test.ts new file mode 100644 index 00000000000000..6133e17ee005e7 --- /dev/null +++ b/test/js/node/fs/abort-signal-leak-read-write-file.test.ts @@ -0,0 +1,6 @@ +import { expect, test } from "bun:test"; +import path from "path"; + +test("should not leak memory with already aborted signals", async () => { + expect([path.join(import.meta.dir, "abort-signal-leak-read-write-file-fixture.ts")]).toRun(); +}); diff --git a/test/js/node/fs/dir.test.ts b/test/js/node/fs/dir.test.ts new file mode 100644 index 00000000000000..3474679c83b514 --- /dev/null +++ b/test/js/node/fs/dir.test.ts @@ -0,0 +1,119 @@ +import { describe, beforeAll, afterAll, beforeEach, afterEach, it, expect } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +function noop() {} +describe("fs.opendir", () => { + // TODO: validatePath + // it.each([1, 0, null, undefined, function foo() {}, Symbol.for("foo")])( + // "throws if the path is not a string: %p", + // (path: any) => { + // expect(() => fs.opendir(path, noop)).toThrow(/The "path" argument must be of type string/); + // }, + // ); + + it("throws if callback is not provided", () => { + expect(() => fs.opendir("foo")).toThrow(/The "callback" argument must be of type function/); + }); +}); + +describe("fs.Dir", () => { + describe("given an empty temp directory", () => { + let dirname: string; + + beforeAll(() => { + const name = "dir-sync.test." + String(Math.random() * 100).substring(0, 6); + dirname = path.join(os.tmpdir(), name); + fs.mkdirSync(dirname); + }); + + afterAll(() => { + fs.rmdirSync(dirname, { recursive: true }); + }); + + describe("when an empty directory is opened", () => { + let dir: fs.Dir; + + beforeEach(() => { + dir = fs.opendirSync(dirname); + }); + + afterEach(() => { + try { + dir.closeSync(); + } catch { + /* suppress */ + } + }); + + it("returns a Dir instance", () => { + expect(dir).toBeDefined(); + expect(dir).toBeInstanceOf(fs.Dir); + }); + + describe("reading from the directory", () => { + it.each([0, 1, false, "foo", {}])("throws if passed a non-function callback (%p)", badCb => { + expect(() => dir.read(badCb)).toThrow(/The "callback" argument must be of type function/); + }); + + it("it can be read synchronously, even though no entries exist", () => { + for (let i = 0; i < 5; i++) { + const actual = dir.readSync(); + expect(actual).toBeNull(); + } + }); + + it("can be read asynchronously, even though no entries exist", async () => { + const actual = await dir.read(); + expect(actual).toBeNull(); + }); + + it("can be read asynchronously with callbacks, even though no entries exist", async () => { + const actual = await new Promise((resolve, reject) => { + dir.read((err, ent) => { + if (err) reject(err); + else resolve(ent); + }); + }); + expect(actual).toBeNull(); + }); + }); // + + it("can be closed asynchronously", async () => { + const actual = await dir.close(); + expect(actual).toBeUndefined(); + }); + + it("can be closed asynchronously with callbacks", async () => { + const actual = await new Promise((resolve, reject) => { + dir.close(err => { + if (err) reject(err); + else resolve(); + }); + }); + expect(actual).toBeUndefined(); + }); + + it("can be closed synchronously", () => { + expect(dir.closeSync()).toBeUndefined(); + }); + + describe("when closed", () => { + beforeEach(async () => { + await dir.close(); + }); + + it('attempts to close again will throw "Directory handle was closed"', () => { + expect(() => dir.closeSync()).toThrow("Directory handle was closed"); + expect(() => dir.close()).toThrow("Directory handle was closed"); + }); + + it("attempts to read will throw", () => { + expect(() => dir.readSync()).toThrow("Directory handle was closed"); + expect(() => dir.read()).toThrow("Directory handle was closed"); + }); + }); // + }); // + }); // +}); // diff --git a/test/js/node/fs/fs.test.ts b/test/js/node/fs/fs.test.ts index 7336c607b7a525..11086faf8ba78d 100644 --- a/test/js/node/fs/fs.test.ts +++ b/test/js/node/fs/fs.test.ts @@ -42,7 +42,7 @@ import fs, { writevSync, } from "node:fs"; import * as os from "node:os"; -import { dirname, relative, resolve } from "node:path"; +import path, { dirname, relative, resolve } from "node:path"; import { promisify } from "node:util"; import _promises, { type FileHandle } from "node:fs/promises"; @@ -2431,7 +2431,9 @@ describe("fs/promises", () => { expect(bun.length).toEqual(node.length); expect([...new Set(node.map(v => v.parentPath ?? v.path))]).toEqual([full]); expect([...new Set(bun.map(v => v.parentPath ?? v.path))]).toEqual([full]); - expect(bun.map(v => join(v.parentPath ?? v.path, v.name)).sort()).toEqual(node.map(v => join(v.path, v.name)).sort()); + expect(bun.map(v => join(v.parentPath ?? v.path, v.name)).sort()).toEqual( + node.map(v => join(v.path, v.name)).sort(), + ); }, 100000); it("readdir(path, {withFileTypes: true, recursive: true}) produces the same result as Node.js", async () => { @@ -2466,7 +2468,9 @@ describe("fs/promises", () => { const node = JSON.parse(text); expect(bun.length).toEqual(node.length); expect(new Set(bun.map(v => v.parentPath ?? v.path))).toEqual(new Set(node.map(v => v.path))); - expect(bun.map(v => join(v.parentPath ?? v.path, v.name)).sort()).toEqual(node.map(v => join(v.path, v.name)).sort()); + expect(bun.map(v => join(v.parentPath ?? v.path, v.name)).sort()).toEqual( + node.map(v => join(v.path, v.name)).sort(), + ); }, 100000); it("readdirSync(path, {withFileTypes: true, recursive: true}) produces the same result as Node.js", async () => { @@ -2501,7 +2505,9 @@ describe("fs/promises", () => { const node = JSON.parse(text); expect(bun.length).toEqual(node.length); expect(new Set(bun.map(v => v.parentPath ?? v.path))).toEqual(new Set(node.map(v => v.path))); - expect(bun.map(v => join(v.parentPath ?? v.path, v.name)).sort()).toEqual(node.map(v => join(v.path, v.name)).sort()); + expect(bun.map(v => join(v.parentPath ?? v.path, v.name)).sort()).toEqual( + node.map(v => join(v.path, v.name)).sort(), + ); }, 100000); for (let withFileTypes of [false, true] as const) { @@ -3528,3 +3534,115 @@ it("fs.statfs should work with bigint", async () => { expect(stats[k]).toBeTypeOf("bigint"); } }); + +it("fs.Stat constructor", () => { + expect(new Stats()).toMatchObject({ + "atimeMs": undefined, + "birthtimeMs": undefined, + "blksize": undefined, + "blocks": undefined, + "ctimeMs": undefined, + "dev": undefined, + "gid": undefined, + "ino": undefined, + "mode": undefined, + "mtimeMs": undefined, + "nlink": undefined, + "rdev": undefined, + "size": undefined, + "uid": undefined, + }); +}); + +it("fs.Stat constructor with options", () => { + // @ts-ignore + expect(new Stats(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)).toMatchObject({ + atimeMs: 10, + birthtimeMs: 13, + blksize: 6, + blocks: 9, + ctimeMs: 12, + dev: 0, + gid: 4, + ino: 7, + mode: 1, + mtimeMs: 11, + nlink: 2, + rdev: 5, + size: 8, + uid: 3, + }); +}); + +it("fs.Stat.atime reflects date matching Node.js behavior", () => { + { + const date = new Date(); + const stats = new Stats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + stats.atime = date; + expect(stats.atime).toBe(date); + } + + { + const stats = new Stats(); + expect(stats.atime.getTime()).toEqual(new Date(undefined).getTime()); + } + + { + const stats = new Stats(); + const now = Date.now(); + stats.atimeMs = now; + expect(stats.atime).toEqual(new Date(now)); + } + + { + const stats = new Stats(); + stats.atimeMs = 0; + expect(stats.atime).toEqual(new Date(0)); + const now = Date.now(); + stats.atimeMs = now; + expect(stats.atime).toEqual(new Date(0)); + } +}); + +describe('kernel32 long path conversion does not mangle "../../path" into "path"', () => { + const tmp1 = tempDirWithFiles("longpath", { + "a/b/config": "true", + }); + const tmp2 = tempDirWithFiles("longpath", { + "a/b/hello": "true", + "config": "true", + }); + const workingDir1 = path.join(tmp1, "a/b"); + const workingDir2 = path.join(tmp2, "a/b"); + const nonExistTests = [ + ["existsSync", 'assert.strictEqual(fs.existsSync("../../config"), false)'], + ["accessSync", 'assert.throws(() => fs.accessSync("../../config"), { code: "ENOENT" })'], + ]; + const existTests = [ + ["existsSync", 'assert.strictEqual(fs.existsSync("../../config"), true)'], + ["accessSync", 'assert.strictEqual(fs.accessSync("../../config"), null)'], + ]; + + for (const [name, code] of nonExistTests) { + it(`${name} (not existing)`, () => { + const { success } = spawnSync({ + cmd: [bunExe(), "-e", code], + cwd: workingDir1, + stdio: ["ignore", "inherit", "inherit"], + env: bunEnv, + }); + expect(success).toBeTrue(); + }); + } + for (const [name, code] of existTests) { + it(`${name} (existing)`, () => { + const { success } = spawnSync({ + cmd: [bunExe(), "-e", code], + cwd: workingDir2, + stdio: ["ignore", "inherit", "inherit"], + env: bunEnv, + }); + expect(success).toBeTrue(); + }); + } +}); diff --git a/test/js/node/fs/glob.test.ts b/test/js/node/fs/glob.test.ts new file mode 100644 index 00000000000000..93cd38063fe765 --- /dev/null +++ b/test/js/node/fs/glob.test.ts @@ -0,0 +1,132 @@ +/** + * @note `fs.glob` et. al. are powered by {@link Bun.Glob}, which is extensively + * tested elsewhere. These tests check API compatibility with Node.js. + */ +import fs from "node:fs"; +import { describe, beforeAll, afterAll, it, expect } from "bun:test"; +import { isWindows, tempDirWithFiles } from "harness"; + +let tmp: string; +beforeAll(() => { + tmp = tempDirWithFiles("fs-glob", { + "foo.txt": "foo", + a: { + "bar.txt": "bar", + "baz.js": "baz", + }, + }); +}); + +afterAll(() => { + return fs.promises.rmdir(tmp, { recursive: true }); +}); + +describe("fs.glob", () => { + it("has a length of 3", () => { + expect(fs).toHaveProperty("glob"); + expect(typeof fs.glob).toEqual("function"); + expect(fs.glob).toHaveLength(3); + }); + + it("is named 'glob'", () => { + expect(fs.glob.name).toEqual("glob"); + }); + + it("when successful, passes paths to the callback", done => { + fs.glob("*.txt", { cwd: tmp }, (err, paths) => { + expect(err).toBeNull(); + expect(paths.sort()).toStrictEqual(["foo.txt"]); + done(); + }); + }); + + it("can filter out files", done => { + const exclude = (path: string) => path.endsWith(".js"); + fs.glob("a/*", { cwd: tmp, exclude }, (err, paths) => { + if (err) done(err); + if (isWindows) { + expect(paths).toStrictEqual(["a\\bar.txt"]); + } else { + expect(paths).toStrictEqual(["a/bar.txt"]); + } + done(); + }); + }); + + describe("invalid arguments", () => { + it("throws if no callback is provided", () => { + expect(() => fs.glob("*.txt")).toThrow(TypeError); + expect(() => fs.glob("*.txt", undefined)).toThrow(TypeError); + expect(() => fs.glob("*.txt", { cwd: tmp })).toThrow(TypeError); + expect(() => fs.glob("*.txt", { cwd: tmp }, undefined)).toThrow(TypeError); + }); + }); +}); // + +describe("fs.globSync", () => { + it("has a length of 2", () => { + expect(fs).toHaveProperty("globSync"); + expect(typeof fs.globSync).toBe("function"); + expect(fs.globSync).toHaveLength(2); + }); + + it("is named 'globSync'", () => { + expect(fs.globSync.name).toEqual("globSync"); + }); + + it.each([ + ["*.txt", ["foo.txt"]], + ["a/**", isWindows ? ["a\\bar.txt", "a\\baz.js"] : ["a/bar.txt", "a/baz.js"]], + ])("fs.glob(%p, { cwd: /tmp/fs-glob }) === %p", (pattern, expected) => { + expect(fs.globSync(pattern, { cwd: tmp }).sort()).toStrictEqual(expected); + }); + + describe("when process.cwd() is set", () => { + let oldProcessCwd: () => string; + beforeAll(() => { + oldProcessCwd = process.cwd; + process.cwd = () => tmp; + }); + afterAll(() => { + process.cwd = oldProcessCwd; + }); + + it("respects the new cwd", () => { + expect(fs.globSync("*.txt")).toStrictEqual(["foo.txt"]); + }); + }); + + it("can filter out files", () => { + const exclude = (path: string) => path.endsWith(".js"); + const expected = isWindows ? ["a\\bar.txt"] : ["a/bar.txt"]; + expect(fs.globSync("a/*", { cwd: tmp, exclude })).toStrictEqual(expected); + }); + + describe("invalid arguments", () => { + // TODO: GlobSet + it("does not support arrays of patterns yet", () => { + expect(() => fs.globSync(["*.txt"])).toThrow(TypeError); + }); + }); +}); // + +describe("fs.promises.glob", () => { + it("has a length of 2", () => { + expect(fs.promises).toHaveProperty("glob"); + expect(typeof fs.promises.glob).toBe("function"); + expect(fs.promises.glob).toHaveLength(2); + }); + + it("is named 'glob'", () => { + expect(fs.promises.glob.name).toEqual("glob"); + }); + + it("returns an AsyncIterable over matched paths", async () => { + const iter = fs.promises.glob("*.txt", { cwd: tmp }); + // FIXME: .toHaveProperty does not support symbol keys + expect(iter[Symbol.asyncIterator]).toBeDefined(); + for await (const path of iter) { + expect(path).toMatch(/\.txt$/); + } + }); +}); // diff --git a/test/js/node/http/node-http-ref-fixture.js b/test/js/node/http/node-http-ref-fixture.js index 78ef0984296023..b5fd7d55d28ffc 100644 --- a/test/js/node/http/node-http-ref-fixture.js +++ b/test/js/node/http/node-http-ref-fixture.js @@ -1,8 +1,9 @@ import { createServer } from "http"; +const SIGNAL = process.platform === "linux" ? "SIGUSR2" : "SIGUSR1"; var server = createServer((req, res) => { res.end(); }).listen(0, async (err, hostname, port) => { - process.on("SIGUSR1", async () => { + process.on(SIGNAL, async () => { server.unref(); // check that the server is still running @@ -15,5 +16,5 @@ var server = createServer((req, res) => { if (resp.status !== 200) { process.exit(42); } - process.kill(process.pid, "SIGUSR1"); + process.kill(process.pid, SIGNAL); }); diff --git a/test/js/node/os/os.test.js b/test/js/node/os/os.test.js index a887b113cd0608..034b7645398a8d 100644 --- a/test/js/node/os/os.test.js +++ b/test/js/node/os/os.test.js @@ -41,7 +41,20 @@ it("setPriority", () => { }); it("loadavg", () => { - expect(os.loadavg().length === 3).toBe(true); + if (isWindows) { + expect(os.loadavg()).toEqual([0, 0, 0]); + } else { + const out = Bun.spawnSync(["uptime"]).stdout.toString(); + const regex = /load averages?: ([\d\.]+),? ([\d\.]+),? ([\d\.]+)/; + const result = regex.exec(out); + const expected = [parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3])]; + const actual = os.loadavg(); + expect(actual).toBeArrayOfSize(3); + for (let i = 0; i < 3; i++) { + // This is quite a lenient range, just in case the load average is changing rapidly + expect(actual[i]).toBeWithin(expected[i] / 2 - 0.5, expected[i] * 2 + 0.5); + } + } }); it("homedir", () => { diff --git a/test/js/node/process/process-signal-handler.fixture.js b/test/js/node/process/process-signal-handler.fixture.js index 77d9d09f4c59c5..8d2990fd025e47 100644 --- a/test/js/node/process/process-signal-handler.fixture.js +++ b/test/js/node/process/process-signal-handler.fixture.js @@ -49,20 +49,21 @@ function done2() { } } -const SIGUSR1 = os.constants.signals.SIGUSR1; const SIGUSR2 = os.constants.signals.SIGUSR2; switch (process.argv.at(-1)) { case "SIGUSR1": { - process.on("SIGUSR1", function () { - checkSignal("SIGUSR1", arguments); + const signalName = process.platform === "linux" ? "SIGUSR2" : "SIGUSR1"; + const signalNumber = os.constants.signals[signalName]; + process.on(signalName, function () { + checkSignal(signalName, arguments); done(); }); - process.on("SIGUSR1", function () { - checkSignal("SIGUSR1", arguments); + process.on(signalName, function () { + checkSignal(signalName, arguments); done(); }); - raise(SIGUSR1); + raise(signalNumber); break; } case "SIGUSR2": { diff --git a/test/js/node/process/process-stdin.test.ts b/test/js/node/process/process-stdin.test.ts new file mode 100644 index 00000000000000..011b7137ac3587 --- /dev/null +++ b/test/js/node/process/process-stdin.test.ts @@ -0,0 +1,30 @@ +import { test, expect } from "bun:test"; +import { bunEnv, bunExe, isWindows } from "harness"; + +test("pipe does the right thing", async () => { + // Note: Bun.spawnSync uses memfd_create on Linux for pipe, which means we see + // it as a file instead of a tty + const result = Bun.spawn({ + cmd: [bunExe(), "-e", "console.log(typeof process.stdin.ref)"], + stdin: "pipe", + stdout: "pipe", + stderr: "inherit", + env: bunEnv, + }); + + expect((await new Response(result.stdout).text()).trim()).toBe("function"); + expect(await result.exited).toBe(0); +}); + +test("file does the right thing", async () => { + const result = Bun.spawn({ + cmd: [bunExe(), "-e", "console.log(typeof process.stdin.ref)"], + stdin: Bun.file(import.meta.path), + stdout: "pipe", + stderr: "inherit", + env: bunEnv, + }); + + expect((await new Response(result.stdout).text()).trim()).toBe("undefined"); + expect(await result.exited).toBe(0); +}); diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index 965105f56bf5a9..b4c71924f9140f 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -319,7 +319,48 @@ it("process.execArgv", () => { }); it("process.binding", () => { - expect(() => process.binding("buffer")).toThrow(); + expect(() => process.binding("async_wrap")).toThrow(); + expect(() => process.binding("buffer")).not.toThrow(); + expect(() => process.binding("cares_wrap")).toThrow(); + expect(() => process.binding("config")).not.toThrow(); + expect(() => process.binding("constants")).not.toThrow(); + expect(() => process.binding("contextify")).toThrow(); + expect(() => process.binding("crypto")).toThrow(); + expect(() => process.binding("crypto/x509")).not.toThrow(); + expect(() => process.binding("fs")).toThrow(); + expect(() => process.binding("fs_event_wrap")).toThrow(); + expect(() => process.binding("http_parser")).toThrow(); + expect(() => process.binding("icu")).toThrow(); + expect(() => process.binding("inspector")).toThrow(); + expect(() => process.binding("js_stream")).toThrow(); + expect(() => process.binding("natives")).not.toThrow(); + expect(() => process.binding("os")).toThrow(); + expect(() => process.binding("pipe_wrap")).toThrow(); + expect(() => process.binding("process_wrap")).toThrow(); + expect(() => process.binding("signal_wrap")).toThrow(); + expect(() => process.binding("spawn_sync")).toThrow(); + expect(() => process.binding("stream_wrap")).toThrow(); + expect(() => process.binding("tcp_wrap")).toThrow(); + expect(() => process.binding("tls_wrap")).toThrow(); + expect(() => process.binding("tty_wrap")).not.toThrow(); + expect(() => process.binding("udp_wrap")).toThrow(); + expect(() => process.binding("url")).toThrow(); + expect(() => process.binding("util")).not.toThrow(); + expect(() => process.binding("uv")).not.toThrow(); + expect(() => process.binding("v8")).toThrow(); + expect(() => process.binding("zlib")).toThrow(); + + expect(() => process.binding()).toThrow(); + expect(() => process.binding(10)).toThrow(); + expect(() => process.binding(10n)).toThrow(); + expect(() => process.binding(null)).toThrow(); + expect(() => process.binding(true)).toThrow(); + expect(() => process.binding("")).toThrow(); + expect(() => process.binding(function () {})).toThrow(); + expect(() => process.binding(() => {})).toThrow(); + expect(() => process.binding(Symbol("ab"))).toThrow(); + expect(() => process.binding({})).toThrow(); + expect(() => process.binding(Object.freeze({ __proto__: null }))).toThrow(); }); it("process.argv in testing", () => { diff --git a/test/js/node/test/parallel/needs-test/test-assert.js b/test/js/node/test/parallel/needs-test/test-assert.js index a18ee87a3833d3..aa302f1f74f83c 100644 --- a/test/js/node/test/parallel/needs-test/test-assert.js +++ b/test/js/node/test/parallel/needs-test/test-assert.js @@ -1049,7 +1049,7 @@ test('Additional asserts', () => { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', // message: 'The "error" argument must be of type Object, Error, Function or RegExp. Received: "Error message"', - message: 'The "error" argument must be of type Object, Error, Function or RegExp.' + invalidArgTypeHelper('Error message'), + message: 'The "error" argument must be of type Object, Error, Function, or RegExp.' + invalidArgTypeHelper('Error message'), } ); @@ -1059,7 +1059,7 @@ test('Additional asserts', () => { () => assert.throws(() => {}, input), { code: 'ERR_INVALID_ARG_TYPE', - message: 'The "error" argument must be of type Object, Error, Function or RegExp.' + invalidArgTypeHelper(input) + message: 'The "error" argument must be of type Object, Error, Function, or RegExp.' + invalidArgTypeHelper(input) } ); @@ -1318,7 +1318,7 @@ test('Additional assert', () => { '\n' + "+ 'test test'\n" + "- 'test foobar'\n" + - ' ^\n', + ' ^\n', } ); @@ -1597,5 +1597,3 @@ test('assert/strict exists', () => { /* eslint-enable no-restricted-syntax */ /* eslint-enable no-restricted-properties */ - - diff --git a/test/js/node/test/parallel/test-buffer-concat.js b/test/js/node/test/parallel/test-buffer-concat.js new file mode 100644 index 00000000000000..2e7541fb58b063 --- /dev/null +++ b/test/js/node/test/parallel/test-buffer-concat.js @@ -0,0 +1,100 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); + +const zero = []; +const one = [ Buffer.from('asdf') ]; +const long = []; +for (let i = 0; i < 10; i++) long.push(Buffer.from('asdf')); + +const flatZero = Buffer.concat(zero); +const flatOne = Buffer.concat(one); +const flatLong = Buffer.concat(long); +const flatLongLen = Buffer.concat(long, 40); + +assert.strictEqual(flatZero.length, 0); +assert.strictEqual(flatOne.toString(), 'asdf'); + +const check = 'asdf'.repeat(10); + +// A special case where concat used to return the first item, +// if the length is one. This check is to make sure that we don't do that. +assert.notStrictEqual(flatOne, one[0]); +assert.strictEqual(flatLong.toString(), check); +assert.strictEqual(flatLongLen.toString(), check); + +[undefined, null, Buffer.from('hello')].forEach((value) => { + assert.throws(() => { + Buffer.concat(value); + }, { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "list" argument must be an instance of Array.' + + `${common.invalidArgTypeHelper(value)}` + }); +}); + +[[42], ['hello', Buffer.from('world')]].forEach((value) => { + assert.throws(() => { + Buffer.concat(value); + }, { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "list[0]" argument must be an instance of Buffer ' + + `or Uint8Array.${common.invalidArgTypeHelper(value[0])}` + }); +}); + +assert.throws(() => { + Buffer.concat([Buffer.from('hello'), 3]); +}, { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "list[1]" argument must be an instance of Buffer ' + + 'or Uint8Array. Received type number (3)' +}); + +// eslint-disable-next-line node-core/crypto-check +const random10 = common.hasCrypto ? + require('crypto').randomBytes(10) : + Buffer.alloc(10, 1); +const empty = Buffer.alloc(0); + +assert.notDeepStrictEqual(random10, empty); +assert.notDeepStrictEqual(random10, Buffer.alloc(10)); + +assert.deepStrictEqual(Buffer.concat([], 100), empty); +assert.deepStrictEqual(Buffer.concat([random10], 0), empty); +assert.deepStrictEqual(Buffer.concat([random10], 10), random10); +assert.deepStrictEqual(Buffer.concat([random10, random10], 10), random10); +assert.deepStrictEqual(Buffer.concat([empty, random10]), random10); +assert.deepStrictEqual(Buffer.concat([random10, empty, empty]), random10); + +// The tail should be zero-filled +assert.deepStrictEqual(Buffer.concat([empty], 100), Buffer.alloc(100)); +assert.deepStrictEqual(Buffer.concat([empty], 4096), Buffer.alloc(4096)); +assert.deepStrictEqual( + Buffer.concat([random10], 40), + Buffer.concat([random10, Buffer.alloc(30)])); + +assert.deepStrictEqual(Buffer.concat([new Uint8Array([0x41, 0x42]), + new Uint8Array([0x43, 0x44])]), + Buffer.from('ABCD')); diff --git a/test/js/node/test/parallel/test-buffer-copy.js b/test/js/node/test/parallel/test-buffer-copy.js new file mode 100644 index 00000000000000..16a638a51181e6 --- /dev/null +++ b/test/js/node/test/parallel/test-buffer-copy.js @@ -0,0 +1,237 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); + +const b = Buffer.allocUnsafe(1024); +const c = Buffer.allocUnsafe(512); + +let cntr = 0; + +{ + // copy 512 bytes, from 0 to 512. + b.fill(++cntr); + c.fill(++cntr); + const copied = b.copy(c, 0, 0, 512); + assert.strictEqual(copied, 512); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], b[i]); + } +} + +{ + // Current behavior is to coerce values to integers. + b.fill(++cntr); + c.fill(++cntr); + const copied = b.copy(c, '0', '0', '512'); + assert.strictEqual(copied, 512); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], b[i]); + } +} + +{ + // Floats will be converted to integers via `Math.floor` + b.fill(++cntr); + c.fill(++cntr); + const copied = b.copy(c, 0, 0, 512.5); + assert.strictEqual(copied, 512); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], b[i]); + } +} + +{ + // Copy c into b, without specifying sourceEnd + b.fill(++cntr); + c.fill(++cntr); + const copied = c.copy(b, 0, 0); + assert.strictEqual(copied, c.length); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(b[i], c[i]); + } +} + +{ + // Copy c into b, without specifying sourceStart + b.fill(++cntr); + c.fill(++cntr); + const copied = c.copy(b, 0); + assert.strictEqual(copied, c.length); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(b[i], c[i]); + } +} + +{ + // Copied source range greater than source length + b.fill(++cntr); + c.fill(++cntr); + const copied = c.copy(b, 0, 0, c.length + 1); + assert.strictEqual(copied, c.length); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(b[i], c[i]); + } +} + +{ + // Copy longer buffer b to shorter c without targetStart + b.fill(++cntr); + c.fill(++cntr); + const copied = b.copy(c); + assert.strictEqual(copied, c.length); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], b[i]); + } +} + +{ + // Copy starting near end of b to c + b.fill(++cntr); + c.fill(++cntr); + const copied = b.copy(c, 0, b.length - Math.floor(c.length / 2)); + assert.strictEqual(copied, Math.floor(c.length / 2)); + for (let i = 0; i < Math.floor(c.length / 2); i++) { + assert.strictEqual(c[i], b[b.length - Math.floor(c.length / 2) + i]); + } + for (let i = Math.floor(c.length / 2) + 1; i < c.length; i++) { + assert.strictEqual(c[c.length - 1], c[i]); + } +} + +{ + // Try to copy 513 bytes, and check we don't overrun c + b.fill(++cntr); + c.fill(++cntr); + const copied = b.copy(c, 0, 0, 513); + assert.strictEqual(copied, c.length); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], b[i]); + } +} + +{ + // copy 768 bytes from b into b + b.fill(++cntr); + b.fill(++cntr, 256); + const copied = b.copy(b, 0, 256, 1024); + assert.strictEqual(copied, 768); + for (let i = 0; i < b.length; i++) { + assert.strictEqual(b[i], cntr); + } +} + +// Copy string longer than buffer length (failure will segfault) +const bb = Buffer.allocUnsafe(10); +bb.fill('hello crazy world'); + + +// Try to copy from before the beginning of b. Should not throw. +b.copy(c, 0, 100, 10); + +// Throw with invalid source type +assert.throws( + () => Buffer.prototype.copy.call(0), + { + // code: 'ERR_INVALID_ARG_TYPE', + code: 'ERR_INVALID_THIS', + name: 'TypeError', + } +); + +// Copy throws at negative targetStart +assert.throws( + () => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), -1, 0), + { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "targetStart" is out of range. ' + + 'It must be >= 0 and <= 5. Received -1' + } +); + +// Copy throws at negative sourceStart +assert.throws( + () => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, -1), + { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + } +); + +// Copy throws if sourceStart is greater than length of source +assert.throws( + () => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, 100), + { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + } +); + +{ + // Check sourceEnd resets to targetEnd if former is greater than the latter + b.fill(++cntr); + c.fill(++cntr); + b.copy(c, 0, 0, 1025); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], b[i]); + } +} + +// Throw with negative sourceEnd +assert.throws( + () => b.copy(c, 0, 0, -1), + { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "sourceEnd" is out of range. ' + + 'It must be >= 0 and <= 1024. Received -1' + } +); + +// When sourceStart is greater than sourceEnd, zero copied +assert.strictEqual(b.copy(c, 0, 100, 10), 0); + +// When targetStart > targetLength, zero copied +assert.strictEqual(b.copy(c, 512, 0, 10), 0); + +// Test that the `target` can be a Uint8Array. +{ + const d = new Uint8Array(c); + // copy 512 bytes, from 0 to 512. + b.fill(++cntr); + d.fill(++cntr); + const copied = b.copy(d, 0, 0, 512); + assert.strictEqual(copied, 512); + for (let i = 0; i < d.length; i++) { + assert.strictEqual(d[i], b[i]); + } +} + +// Test that the source can be a Uint8Array, too. +{ + const e = new Uint8Array(b); + // copy 512 bytes, from 0 to 512. + e.fill(++cntr); + c.fill(++cntr); + const copied = Buffer.prototype.copy.call(e, c, 0, 0, 512); + assert.strictEqual(copied, 512); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(c[i], e[i]); + } +} + +// https://github.com/nodejs/node/issues/23668: Do not crash for invalid input. +c.fill('c'); +b.copy(c, 'not a valid offset'); +// Make sure this acted like a regular copy with `0` offset. +assert.deepStrictEqual(c, b.slice(0, c.length)); + +{ + c.fill('C'); + assert.throws(() => { + b.copy(c, { [Symbol.toPrimitive]() { throw new Error('foo'); } }); + }, /foo/); + // No copying took place: + assert.deepStrictEqual(c.toString(), 'C'.repeat(c.length)); +} diff --git a/test/js/node/test/parallel/test-buffer-fill.js b/test/js/node/test/parallel/test-buffer-fill.js new file mode 100644 index 00000000000000..55e5d3399f241f --- /dev/null +++ b/test/js/node/test/parallel/test-buffer-fill.js @@ -0,0 +1,444 @@ +// Flags: --expose-internals +'use strict'; +const common = require('../common'); +const assert = require('assert'); +// const { codes: { ERR_OUT_OF_RANGE } } = require('internal/errors'); +// const { internalBinding } = require('internal/test/binding'); +const SIZE = 28; + +const buf1 = Buffer.allocUnsafe(SIZE); +const buf2 = Buffer.allocUnsafe(SIZE); + +// Default encoding +testBufs('abc'); +testBufs('\u0222aa'); +testBufs('a\u0234b\u0235c\u0236'); +testBufs('abc', 4); +testBufs('abc', 5); +testBufs('abc', SIZE); +testBufs('\u0222aa', 2); +testBufs('\u0222aa', 8); +testBufs('a\u0234b\u0235c\u0236', 4); +testBufs('a\u0234b\u0235c\u0236', 12); +testBufs('abc', 4, 1); +testBufs('abc', 5, 1); +testBufs('\u0222aa', 8, 1); +testBufs('a\u0234b\u0235c\u0236', 4, 1); +testBufs('a\u0234b\u0235c\u0236', 12, 1); + +// UTF8 +testBufs('abc', 'utf8'); +testBufs('\u0222aa', 'utf8'); +testBufs('a\u0234b\u0235c\u0236', 'utf8'); +testBufs('abc', 4, 'utf8'); +testBufs('abc', 5, 'utf8'); +testBufs('abc', SIZE, 'utf8'); +testBufs('\u0222aa', 2, 'utf8'); +testBufs('\u0222aa', 8, 'utf8'); +testBufs('a\u0234b\u0235c\u0236', 4, 'utf8'); +testBufs('a\u0234b\u0235c\u0236', 12, 'utf8'); +testBufs('abc', 4, 1, 'utf8'); +testBufs('abc', 5, 1, 'utf8'); +testBufs('\u0222aa', 8, 1, 'utf8'); +testBufs('a\u0234b\u0235c\u0236', 4, 1, 'utf8'); +testBufs('a\u0234b\u0235c\u0236', 12, 1, 'utf8'); +assert.strictEqual(Buffer.allocUnsafe(1).fill(0).fill('\u0222')[0], 0xc8); + +// BINARY +testBufs('abc', 'binary'); +testBufs('\u0222aa', 'binary'); +testBufs('a\u0234b\u0235c\u0236', 'binary'); +testBufs('abc', 4, 'binary'); +testBufs('abc', 5, 'binary'); +testBufs('abc', SIZE, 'binary'); +testBufs('\u0222aa', 2, 'binary'); +testBufs('\u0222aa', 8, 'binary'); +testBufs('a\u0234b\u0235c\u0236', 4, 'binary'); +testBufs('a\u0234b\u0235c\u0236', 12, 'binary'); +testBufs('abc', 4, 1, 'binary'); +testBufs('abc', 5, 1, 'binary'); +testBufs('\u0222aa', 8, 1, 'binary'); +testBufs('a\u0234b\u0235c\u0236', 4, 1, 'binary'); +testBufs('a\u0234b\u0235c\u0236', 12, 1, 'binary'); + +// LATIN1 +testBufs('abc', 'latin1'); +testBufs('\u0222aa', 'latin1'); +testBufs('a\u0234b\u0235c\u0236', 'latin1'); +testBufs('abc', 4, 'latin1'); +testBufs('abc', 5, 'latin1'); +testBufs('abc', SIZE, 'latin1'); +testBufs('\u0222aa', 2, 'latin1'); +testBufs('\u0222aa', 8, 'latin1'); +testBufs('a\u0234b\u0235c\u0236', 4, 'latin1'); +testBufs('a\u0234b\u0235c\u0236', 12, 'latin1'); +testBufs('abc', 4, 1, 'latin1'); +testBufs('abc', 5, 1, 'latin1'); +testBufs('\u0222aa', 8, 1, 'latin1'); +testBufs('a\u0234b\u0235c\u0236', 4, 1, 'latin1'); +testBufs('a\u0234b\u0235c\u0236', 12, 1, 'latin1'); + +// UCS2 +testBufs('abc', 'ucs2'); +testBufs('\u0222aa', 'ucs2'); +testBufs('a\u0234b\u0235c\u0236', 'ucs2'); +testBufs('abc', 4, 'ucs2'); +testBufs('abc', SIZE, 'ucs2'); +testBufs('\u0222aa', 2, 'ucs2'); +testBufs('\u0222aa', 8, 'ucs2'); +testBufs('a\u0234b\u0235c\u0236', 4, 'ucs2'); +testBufs('a\u0234b\u0235c\u0236', 12, 'ucs2'); +testBufs('abc', 4, 1, 'ucs2'); +testBufs('abc', 5, 1, 'ucs2'); +testBufs('\u0222aa', 8, 1, 'ucs2'); +testBufs('a\u0234b\u0235c\u0236', 4, 1, 'ucs2'); +testBufs('a\u0234b\u0235c\u0236', 12, 1, 'ucs2'); +assert.strictEqual(Buffer.allocUnsafe(1).fill('\u0222', 'ucs2')[0], 0x22); + +// HEX +testBufs('616263', 'hex'); +testBufs('c8a26161', 'hex'); +testBufs('61c8b462c8b563c8b6', 'hex'); +testBufs('616263', 4, 'hex'); +testBufs('616263', 5, 'hex'); +testBufs('616263', SIZE, 'hex'); +testBufs('c8a26161', 2, 'hex'); +testBufs('c8a26161', 8, 'hex'); +testBufs('61c8b462c8b563c8b6', 4, 'hex'); +testBufs('61c8b462c8b563c8b6', 12, 'hex'); +testBufs('616263', 4, 1, 'hex'); +testBufs('616263', 5, 1, 'hex'); +testBufs('c8a26161', 8, 1, 'hex'); +testBufs('61c8b462c8b563c8b6', 4, 1, 'hex'); +testBufs('61c8b462c8b563c8b6', 12, 1, 'hex'); + +assert.throws(() => { + const buf = Buffer.allocUnsafe(SIZE); + + buf.fill('yKJh', 'hex'); +}, { + code: 'ERR_INVALID_ARG_VALUE', + name: 'TypeError' +}); + +assert.throws(() => { + const buf = Buffer.allocUnsafe(SIZE); + + buf.fill('\u0222', 'hex'); +}, { + code: 'ERR_INVALID_ARG_VALUE', + name: 'TypeError' +}); + +// BASE64 +testBufs('YWJj', 'base64'); +testBufs('yKJhYQ==', 'base64'); +testBufs('Yci0Ysi1Y8i2', 'base64'); +testBufs('YWJj', 4, 'base64'); +testBufs('YWJj', SIZE, 'base64'); +testBufs('yKJhYQ==', 2, 'base64'); +testBufs('yKJhYQ==', 8, 'base64'); +testBufs('Yci0Ysi1Y8i2', 4, 'base64'); +testBufs('Yci0Ysi1Y8i2', 12, 'base64'); +testBufs('YWJj', 4, 1, 'base64'); +testBufs('YWJj', 5, 1, 'base64'); +testBufs('yKJhYQ==', 8, 1, 'base64'); +testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64'); +testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64'); + +// BASE64URL +testBufs('YWJj', 'base64url'); +testBufs('yKJhYQ', 'base64url'); +testBufs('Yci0Ysi1Y8i2', 'base64url'); +testBufs('YWJj', 4, 'base64url'); +testBufs('YWJj', SIZE, 'base64url'); +testBufs('yKJhYQ', 2, 'base64url'); +testBufs('yKJhYQ', 8, 'base64url'); +testBufs('Yci0Ysi1Y8i2', 4, 'base64url'); +testBufs('Yci0Ysi1Y8i2', 12, 'base64url'); +testBufs('YWJj', 4, 1, 'base64url'); +testBufs('YWJj', 5, 1, 'base64url'); +testBufs('yKJhYQ', 8, 1, 'base64url'); +testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64url'); +testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64url'); + +// Buffer +function deepStrictEqualValues(buf, arr) { + for (const [index, value] of buf.entries()) { + assert.deepStrictEqual(value, arr[index]); + } +} + +const buf2Fill = Buffer.allocUnsafe(1).fill(2); +deepStrictEqualValues(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]); +deepStrictEqualValues(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]); +deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]); +deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]); +const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill('0102', 'hex'); +deepStrictEqualValues(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]); +deepStrictEqualValues(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]); +deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]); +deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]); + +// Check exceptions +[ + [0, -1], + [0, 0, buf1.length + 1], + ['', -1], + ['', 0, buf1.length + 1], + ['', 1, -1], +].forEach((args) => { + assert.throws( + () => buf1.fill(...args), + { code: 'ERR_OUT_OF_RANGE' } + ); +}); + +assert.throws( + () => buf1.fill('a', 0, buf1.length, 'node rocks!'), + { + code: 'ERR_UNKNOWN_ENCODING', + name: 'TypeError', + message: 'Unknown encoding: node rocks!' + } +); + +[ + ['a', 0, 0, NaN], + ['a', 0, 0, false], +].forEach((args) => { + assert.throws( + () => buf1.fill(...args), + { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "encoding" argument must be of type ' + + `string.${common.invalidArgTypeHelper(args[3])}` + } + ); +}); + +assert.throws( + () => buf1.fill('a', 0, 0, 'foo'), + { + code: 'ERR_UNKNOWN_ENCODING', + name: 'TypeError', + message: 'Unknown encoding: foo' + } +); + +function genBuffer(size, args) { + const b = Buffer.allocUnsafe(size); + return b.fill(0).fill.apply(b, args); +} + +function bufReset() { + buf1.fill(0); + buf2.fill(0); +} + +// This is mostly accurate. Except write() won't write partial bytes to the +// string while fill() blindly copies bytes into memory. To account for that an +// error will be thrown if not all the data can be written, and the SIZE has +// been massaged to work with the input characters. +function writeToFill(string, offset, end, encoding) { + if (typeof offset === 'string') { + encoding = offset; + offset = 0; + end = buf2.length; + } else if (typeof end === 'string') { + encoding = end; + end = buf2.length; + } else if (end === undefined) { + end = buf2.length; + } + + // Should never be reached. + if (offset < 0 || end > buf2.length) + throw new ERR_OUT_OF_RANGE(); + + if (end <= offset) + return buf2; + + offset >>>= 0; + end >>>= 0; + assert(offset <= buf2.length); + + // Convert "end" to "length" (which write understands). + const length = end - offset < 0 ? 0 : end - offset; + + let wasZero = false; + do { + const written = buf2.write(string, offset, length, encoding); + offset += written; + // Safety check in case write falls into infinite loop. + if (written === 0) { + if (wasZero) + throw new Error('Could not write all data to Buffer'); + else + wasZero = true; + } + } while (offset < buf2.length); + + return buf2; +} + +function testBufs(string, offset, length, encoding) { + bufReset(); + buf1.fill.apply(buf1, arguments); + // Swap bytes on BE archs for ucs2 encoding. + assert.deepStrictEqual(buf1.fill.apply(buf1, arguments), + writeToFill.apply(null, arguments)); +} + +// Make sure these throw. +assert.throws( + () => Buffer.allocUnsafe(8).fill('a', -1), + { code: 'ERR_OUT_OF_RANGE' }); +assert.throws( + () => Buffer.allocUnsafe(8).fill('a', 0, 9), + { code: 'ERR_OUT_OF_RANGE' }); + +// Make sure this doesn't hang indefinitely. +Buffer.allocUnsafe(8).fill(''); +Buffer.alloc(8, ''); + +{ + const buf = Buffer.alloc(64, 10); + for (let i = 0; i < buf.length; i++) + assert.strictEqual(buf[i], 10); + + buf.fill(11, 0, buf.length >> 1); + for (let i = 0; i < buf.length >> 1; i++) + assert.strictEqual(buf[i], 11); + for (let i = (buf.length >> 1) + 1; i < buf.length; i++) + assert.strictEqual(buf[i], 10); + + buf.fill('h'); + for (let i = 0; i < buf.length; i++) + assert.strictEqual(buf[i], 'h'.charCodeAt(0)); + + buf.fill(0); + for (let i = 0; i < buf.length; i++) + assert.strictEqual(buf[i], 0); + + buf.fill(null); + for (let i = 0; i < buf.length; i++) + assert.strictEqual(buf[i], 0); + + buf.fill(1, 16, 32); + for (let i = 0; i < 16; i++) + assert.strictEqual(buf[i], 0); + for (let i = 16; i < 32; i++) + assert.strictEqual(buf[i], 1); + for (let i = 32; i < buf.length; i++) + assert.strictEqual(buf[i], 0); +} + +{ + const buf = Buffer.alloc(10, 'abc'); + assert.strictEqual(buf.toString(), 'abcabcabca'); + buf.fill('է'); + assert.strictEqual(buf.toString(), 'էէէէէ'); +} + +// Testing process.binding. Make sure "start" is properly checked for range errors. +// assert.throws( +// () => { process.binding('buffer').fill(Buffer.alloc(1), 1, -1, 0, 1); }, +// { code: 'ERR_OUT_OF_RANGE' } +// ); + +// Make sure "end" is properly checked, even if it's magically mangled using +// Symbol.toPrimitive. +{ + assert.throws(() => { + const end = { + [Symbol.toPrimitive]() { + return 1; + } + }; + Buffer.alloc(1).fill(Buffer.alloc(1), 0, end); + }, { + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "end" argument must be of type number. Received an ' + + 'instance of Object' + }); +} + +// Testing process.binding. Make sure "end" is properly checked for range errors. +// assert.throws( +// () => { internalBinding('buffer').fill(Buffer.alloc(1), 1, 1, -2, 1); }, +// { code: 'ERR_OUT_OF_RANGE' } +// ); + +// Test that bypassing 'length' won't cause an abort. +// assert.throws(() => { +// const buf = Buffer.from('w00t'); +// Object.defineProperty(buf, 'length', { +// value: 1337, +// enumerable: true +// }); +// buf.fill(''); +// }, { +// code: 'ERR_BUFFER_OUT_OF_BOUNDS', +// name: 'RangeError', +// message: 'Attempt to access memory outside buffer bounds' +// }); + +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), + Buffer.from('61006200610062006100620061006200', 'hex')); + +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(15).fill('ab', 'utf16le'), + Buffer.from('610062006100620061006200610062', 'hex')); + +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), + Buffer.from('61006200610062006100620061006200', 'hex')); +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf16le'), + Buffer.from('61006100610061006100610061006100', 'hex')); + +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'), + 'a'.repeat(8)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'), + 'a'.repeat(16)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'), + 'a'.repeat(16)); + +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'), + 'Љ'.repeat(8)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'), + '\t'.repeat(16)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'), + 'Љ'.repeat(8)); + +assert.throws(() => { + const buf = Buffer.from('a'.repeat(1000)); + + buf.fill('This is not correctly encoded', 'hex'); +}, { + code: 'ERR_INVALID_ARG_VALUE', + name: 'TypeError' +}); + + +{ + const bufEmptyString = Buffer.alloc(5, ''); + assert.strictEqual(bufEmptyString.toString(), '\x00\x00\x00\x00\x00'); + + const bufEmptyArray = Buffer.alloc(5, []); + assert.strictEqual(bufEmptyArray.toString(), '\x00\x00\x00\x00\x00'); + + const bufEmptyBuffer = Buffer.alloc(5, Buffer.alloc(5)); + assert.strictEqual(bufEmptyBuffer.toString(), '\x00\x00\x00\x00\x00'); + + const bufZero = Buffer.alloc(5, 0); + assert.strictEqual(bufZero.toString(), '\x00\x00\x00\x00\x00'); +} diff --git a/test/js/node/test/parallel/test-buffer-zero-fill-cli.js b/test/js/node/test/parallel/test-buffer-zero-fill-cli.js new file mode 100644 index 00000000000000..4299f81039b0b5 --- /dev/null +++ b/test/js/node/test/parallel/test-buffer-zero-fill-cli.js @@ -0,0 +1,32 @@ +'use strict'; +// Flags: --zero-fill-buffers + +// when using --zero-fill-buffers, every Buffer and SlowBuffer +// instance must be zero filled upon creation + +require('../common'); +const SlowBuffer = require('buffer').SlowBuffer; +const assert = require('assert'); + +function isZeroFilled(buf) { + for (const n of buf) + if (n > 0) return false; + return true; +} + +// This can be somewhat unreliable because the +// allocated memory might just already happen to +// contain all zeroes. The test is run multiple +// times to improve the reliability. +for (let i = 0; i < 50; i++) { + const bufs = [ + Buffer.alloc(20), + Buffer.allocUnsafe(20), + SlowBuffer(20), + Buffer(20), + new SlowBuffer(20), + ]; + for (const buf of bufs) { + assert(isZeroFilled(buf)); + } +} diff --git a/test/js/node/test/parallel/test-dgram-reuseport.js b/test/js/node/test/parallel/test-dgram-reuseport.js index e5fd6965818d4c..c9b6f7964ab666 100644 --- a/test/js/node/test/parallel/test-dgram-reuseport.js +++ b/test/js/node/test/parallel/test-dgram-reuseport.js @@ -12,6 +12,8 @@ function test() { socket2.close(); })); })); + socket1.on('error', common.mustNotCall()); + socket2.on('error', common.mustNotCall()); } checkSupportReusePort().then(test, () => { diff --git a/test/js/node/test/parallel/test-dgram-send-bad-arguments.js b/test/js/node/test/parallel/test-dgram-send-bad-arguments.js index 83151538a49eab..7257a0aca6a654 100644 --- a/test/js/node/test/parallel/test-dgram-send-bad-arguments.js +++ b/test/js/node/test/parallel/test-dgram-send-bad-arguments.js @@ -35,7 +35,7 @@ function checkArgs(connected) { { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', - message: /The "buffer" argument must be of type (string or an instance of Buffer, TypedArray, or DataView|Buffer, TypedArray, DataView or string)\. Received undefined/ + message: 'The "buffer" argument must be of type string, Buffer, TypedArray, or DataView. Received undefined' } ); @@ -95,7 +95,7 @@ function checkArgs(connected) { { code: 'ERR_BUFFER_OUT_OF_BOUNDS', name: 'RangeError', - message: /"offset" is outside of buffer bounds|Attempt to access memory outside buffer bounds/, + message: '"offset" is outside of buffer bounds', } ); @@ -104,7 +104,7 @@ function checkArgs(connected) { { code: 'ERR_BUFFER_OUT_OF_BOUNDS', name: 'RangeError', - message: /"length" is outside of buffer bounds|Attempt to access memory outside buffer bounds/, + message: '"length" is outside of buffer bounds', } ); @@ -113,7 +113,7 @@ function checkArgs(connected) { { code: 'ERR_BUFFER_OUT_OF_BOUNDS', name: 'RangeError', - message: /"length" is outside of buffer bounds|Attempt to access memory outside buffer bounds/, + message: '"length" is outside of buffer bounds', } ); } @@ -129,7 +129,7 @@ function checkArgs(connected) { { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', - message: /The "buffer" argument must be of type (string or an instance of Buffer, TypedArray, or DataView|Buffer, TypedArray, DataView or string)\. Received type number \(23\)/, + message: 'The "buffer" argument must be of type string, Buffer, TypedArray, or DataView. Received type number (23)' } ); @@ -139,7 +139,8 @@ function checkArgs(connected) { { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', - message: /The "?buffer list arguments(" argument)? must be of type (string or an instance of Buffer, TypedArray, or DataView|Buffer, TypedArray, DataView or string)\. Received an instance of Array/ + message: 'The "buffer list arguments" argument must be of type string, Buffer, TypedArray, or DataView. ' + + 'Received an instance of Array' } ); } diff --git a/test/js/node/test/parallel/test-http-chunk-problem.js b/test/js/node/test/parallel/test-http-chunk-problem.js index 3629b7576600e8..b6b30dbee5beee 100644 --- a/test/js/node/test/parallel/test-http-chunk-problem.js +++ b/test/js/node/test/parallel/test-http-chunk-problem.js @@ -23,11 +23,15 @@ if (process.argv[2] === 'request') { if (process.argv[2] === 'shasum') { const crypto = require('crypto'); const shasum = crypto.createHash('sha1'); + let total = 0; process.stdin.on('data', (d) => { + console.warn("Chunk: " + d.length); + total += d.length; shasum.update(d); }); process.stdin.on('close', () => { + console.warn("Total:", total); process.stdout.write(shasum.digest('hex')); }); @@ -60,8 +64,9 @@ function executeRequest(cb) { { env }, (err, stdout, stderr) => { if (stderr.trim() !== '') { - console.log(stderr); + console.error(stderr); } + console.log(stdout.toString()); assert.ifError(err); assert.strictEqual(stdout.slice(0, 40), '8c206a1a87599f532ce68675536f0b1546900d7a'); diff --git a/test/js/node/test/parallel/test-http-import-websocket.js b/test/js/node/test/parallel/test-http-import-websocket.js new file mode 100644 index 00000000000000..5026d65108f03a --- /dev/null +++ b/test/js/node/test/parallel/test-http-import-websocket.js @@ -0,0 +1,14 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const { + WebSocket: NodeHttpWebSocket, + CloseEvent: NodeHttpCloseEvent, + MessageEvent: NodeHttpMessageEvent +} = require('node:http'); + +// Compare with global objects +assert.strictEqual(NodeHttpWebSocket, WebSocket); +assert.strictEqual(NodeHttpCloseEvent, CloseEvent); +assert.strictEqual(NodeHttpMessageEvent, MessageEvent); diff --git a/test/js/node/test/parallel/test-signal-handler.js b/test/js/node/test/parallel/test-signal-handler.js index 05ec4e7f73faf5..68c97586377214 100644 --- a/test/js/node/test/parallel/test-signal-handler.js +++ b/test/js/node/test/parallel/test-signal-handler.js @@ -30,9 +30,12 @@ if (!common.isMainThread) console.log(`process.pid: ${process.pid}`); -process.on('SIGUSR1', common.mustCall()); +// On Bun in Linux, SIGUSR1 is reserved for the GC. +// So we need to use a different signal. +const SIGNAL = process.platform === 'linux' ? 'SIGUSR2' : 'SIGUSR1'; -process.on('SIGUSR1', common.mustCall(function() { +process.on(SIGNAL, common.mustCall()); +process.on(SIGNAL, common.mustCall(function() { setTimeout(function() { console.log('End.'); process.exit(0); @@ -44,7 +47,7 @@ setInterval(function() { console.log(`running process...${++i}`); if (i === 5) { - process.kill(process.pid, 'SIGUSR1'); + process.kill(process.pid, SIGNAL); } }, 1); diff --git a/test/js/node/test/parallel/test-url-parse-invalid-input.js b/test/js/node/test/parallel/test-url-parse-invalid-input.js index a8ae4838af32c4..8f8a4d40f8c055 100644 --- a/test/js/node/test/parallel/test-url-parse-invalid-input.js +++ b/test/js/node/test/parallel/test-url-parse-invalid-input.js @@ -96,8 +96,8 @@ if (common.hasIntl) { // Warning should only happen once per process. common.expectWarning({ DeprecationWarning: { - // eslint-disable-next-line @stylistic/js/max-len - DEP0169: '`url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.', + // NOTE: this warning is noisy and annoying. We've disabled it intentionally. + // DEP0169: '`url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.', DEP0170: `The URL ${badURLs[0]} is invalid. Future versions of Node.js will throw an error.`, }, }); diff --git a/test/js/node/url/pathToFileURL-leak-fixture.js b/test/js/node/url/pathToFileURL-leak-fixture.js new file mode 100644 index 00000000000000..bc1557a0476adf --- /dev/null +++ b/test/js/node/url/pathToFileURL-leak-fixture.js @@ -0,0 +1,13 @@ +var longPath = Buffer.alloc(1021, "Z").toString(); +const isDebugBuildOfBun = globalThis?.Bun?.revision?.includes("debug"); +import { pathToFileURL } from "url"; +for (let i = 0; i < 1024 * (isDebugBuildOfBun ? 32 : 256); i++) { + pathToFileURL(longPath); +} +Bun.gc(true); +const rss = (process.memoryUsage.rss() / 1024 / 1024) | 0; +console.log("RSS", rss, "MB"); +if (rss > 250) { + // On macOS, this was 860 MB. + throw new Error("RSS is too high. Must be less than 250MB"); +} diff --git a/test/js/node/url/pathToFileURL.test.ts b/test/js/node/url/pathToFileURL.test.ts new file mode 100644 index 00000000000000..bb9815f9106e99 --- /dev/null +++ b/test/js/node/url/pathToFileURL.test.ts @@ -0,0 +1,29 @@ +import { test, expect } from "bun:test"; +import path from "path"; + +test("pathToFileURL doesn't leak memory", () => { + expect([path.join(import.meta.dir, "pathToFileURL-leak-fixture.js")]).toRun(); +}); + +test("pathToFileURL escapes special characters", () => { + const cases = [ + ['\0', '%00'], // '\0' == 0x00 + ['\t', '%09'], // '\t' == 0x09 + ['\n', '%0A'], // '\n' == 0x0A + ['\r', '%0D'], // '\r' == 0x0D + [' ', '%20'], // ' ' == 0x20 + ['"', '%22'], // '"' == 0x22 + ['#', '%23'], // '#' == 0x23 + ['%', '%25'], // '%' == 0x25 + ['?', '%3F'], // '?' == 0x3F + ['[', '%5B'], // '[' == 0x5B + [']', '%5D'], // ']' == 0x5D + ['^', '%5E'], // '^' == 0x5E + ['|', '%7C'], // '|' == 0x7C + ['~', '%7E'], // '~' == 0x7E + ]; + + for (const [input, expected] of cases) { + expect(Bun.pathToFileURL(`${input}`).toString()).toInclude(expected); + } +}); diff --git a/test/js/node/url/url.test.ts b/test/js/node/url/url.test.ts index 004fb499914e83..2fd8fa6277a0ab 100644 --- a/test/js/node/url/url.test.ts +++ b/test/js/node/url/url.test.ts @@ -79,3 +79,10 @@ it("URL constructor throws ERR_MISSING_ARGS", () => { // @ts-expect-error expect(err?.code).toEqual("ERR_MISSING_ARGS"); }); + +// https://github.com/oven-sh/bun/issues/16705 +it("#16705", () => { + expect(Bun.fileURLToPath("file://C:/firebase-gen-%7B%7B%20firebase.gen%20%7D%7D")).toEqual( + process.platform === "win32" ? "C:\\firebase-gen-{{ firebase.gen }}" : "/C:/firebase-gen-{{ firebase.gen }}", + ); +}); diff --git a/test/js/node/util/test-aborted.test.ts b/test/js/node/util/test-aborted.test.ts index d498681f317a25..11af6f00e04d5f 100644 --- a/test/js/node/util/test-aborted.test.ts +++ b/test/js/node/util/test-aborted.test.ts @@ -37,15 +37,32 @@ test("aborted works when provided a resource that was not already aborted", asyn test("aborted with gc cleanup", async () => { const ac = new AbortController(); - const abortedPromise = aborted(ac.signal, {}); + let finalized = false; + // make a FinalizationRegistry to tell us when the second argument to aborted() + // has been garbage collected + const registry = new FinalizationRegistry(() => { + finalized = true; + }); + const abortedPromise = (() => { + const gcMe = {}; + registry.register(gcMe, undefined); + const abortedPromise = aborted(ac.signal, gcMe); + return abortedPromise; + // gcMe is now out of scope and eligible to be collected + })(); + abortedPromise.then(() => { + throw new Error("this promise should never resolve"); + }); - await new Promise(resolve => setImmediate(resolve)); - Bun.gc(true); + // wait for the object to be GC'd by ticking the event loop and forcing garbage collection + while (!finalized) { + await new Promise(resolve => setImmediate(resolve)); + Bun.gc(true); + } ac.abort(); expect(ac.signal.aborted).toBe(true); expect(getEventListeners(ac.signal, "abort").length).toBe(0); - return expect(await abortedPromise).toBeUndefined(); }); test("fails with error if not provided abort signal", async () => { diff --git a/test/js/node/util/test-util-types.test.js b/test/js/node/util/test-util-types.test.js index 084da3bfaceaf9..68d622e2573fc4 100644 --- a/test/js/node/util/test-util-types.test.js +++ b/test/js/node/util/test-util-types.test.js @@ -277,3 +277,29 @@ test("isKeyObject", () => { expect(types.isKeyObject(null)).toBeFalse(); expect(types.isKeyObject(undefined)).toBeFalse(); }); + +test("#11780", () => { + let resolveError; + try { + resolveError = require("OOGA_BOOGA"); + } catch (e) { + resolveError = e; + } + expect(resolveError.constructor.name).toBe("ResolveMessage"); + expect(types.isNativeError(resolveError)).toBeTrue(); + + const badCode = ` +export default /BADD~!!!!; + + `; + const blob = new Blob([badCode], { type: "application/javascript" }); + const url = URL.createObjectURL(blob); + let buildError; + try { + require(url); + } catch (e) { + buildError = e; + } + expect(types.isNativeError(buildError)).toBeTrue(); + expect(buildError.constructor.name).toBe("BuildMessage"); +}); diff --git a/test/js/sql/docker/Dockerfile b/test/js/sql/docker/Dockerfile index 923a232e9f5f3b..210a53f847a5b3 100644 --- a/test/js/sql/docker/Dockerfile +++ b/test/js/sql/docker/Dockerfile @@ -59,8 +59,7 @@ RUN mkdir -p /etc/postgresql && touch /etc/postgresql/pg_hba.conf && \ echo "host replication all 127.0.0.1/32 trust" >> /etc/postgresql/pg_hba.conf && \ echo "host replication all ::1/128 trust" >> /etc/postgresql/pg_hba.conf RUN mkdir -p /docker-entrypoint-initdb.d && \ - echo "ALTER SYSTEM SET max_prepared_transactions = '100';" > /docker-entrypoint-initdb.d/configure-postgres.sql - + echo "ALTER SYSTEM SET max_prepared_transactions = '1000';ALTER SYSTEM SET max_connections = '2000';" > /docker-entrypoint-initdb.d/configure-postgres.sql # Set environment variables ENV POSTGRES_HOST_AUTH_METHOD=trust ENV POSTGRES_USER=postgres diff --git a/test/js/sql/sql.test.ts b/test/js/sql/sql.test.ts index f79c76927814f8..a00acc03d0364c 100644 --- a/test/js/sql/sql.test.ts +++ b/test/js/sql/sql.test.ts @@ -1,4 +1,4 @@ -import { sql, SQL } from "bun"; +import { sql, SQL, randomUUIDv7 } from "bun"; const postgres = (...args) => new sql(...args); import { expect, test, mock, beforeAll, afterAll } from "bun:test"; import { $ } from "bun"; @@ -61,9 +61,7 @@ async function startContainer(): Promise<{ port: number; containerName: string } } // Start the container - await execAsync( - `${dockerCLI} run -d --name ${containerName} -p ${port}:5432 custom-postgres`, - ); + await execAsync(`${dockerCLI} run -d --name ${containerName} -p ${port}:5432 custom-postgres`); // Wait for PostgreSQL to be ready await waitForPostgres(port); @@ -99,6 +97,9 @@ if (isDockerEnabled()) { afterAll(async () => { try { await execAsync(`${dockerCLI} stop -t 0 ${container.containerName}`); + } catch (error) {} + + try { await execAsync(`${dockerCLI} rm -f ${container.containerName}`); } catch (error) {} }); @@ -265,6 +266,28 @@ if (isDockerEnabled()) { expect(result).toEqual([{ x: 3 }]); }); + test("should not timeout in long results", async () => { + await using db = postgres({ ...options, max: 1, idleTimeout: 5 }); + using sql = await db.reserve(); + const random_name = "test_" + randomUUIDv7("hex").replaceAll("-", ""); + + await sql`CREATE TEMPORARY TABLE ${sql(random_name)} (id int, name text)`; + const promises: Promise[] = []; + for (let i = 0; i < 10_000; i++) { + promises.push(sql`INSERT INTO ${sql(random_name)} VALUES (${i}, ${"test" + i})`); + if (i % 50 === 0 && i > 0) { + await Promise.all(promises); + promises.length = 0; + } + } + await Promise.all(promises); + await sql`SELECT * FROM ${sql(random_name)}`; + await sql`SELECT * FROM ${sql(random_name)}`; + await sql`SELECT * FROM ${sql(random_name)}`; + + expect().pass(); + }, 10_000); + test("Handles numeric column names", async () => { // deliberately out of order const result = await sql`select 1 as "1", 2 as "2", 3 as "3", 0 as "0"`; @@ -275,6 +298,28 @@ if (isDockerEnabled()) { Bun.inspect(result); }); + test("query string memory leak test", async () => { + Bun.gc(true); + const rss = process.memoryUsage.rss(); + for (let potato of Array.from({ length: 8 * 1024 }, a => "okkk" + a)) { + await sql` + select 1 as abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde + , 2 as ${sql(potato)} + `; + } + + Bun.gc(true); + const after = process.memoryUsage.rss(); + console.log({ after, rss }); + // Previously: + // { + // after: 507150336, + // rss: 49152000, + // } + // ~440 MB. + expect((after - rss) / 1024 / 1024).toBeLessThan(200); + }); + // Last one wins. test("Handles duplicate numeric column names", async () => { const result = await sql`select 1 as "1", 2 as "1", 3 as "1"`; @@ -625,7 +670,7 @@ if (isDockerEnabled()) { }); test("Transaction requests are executed implicitly", async () => { - const sql = postgres({ ...options, debug: true, idle_timeout: 1, fetch_types: false }); + await using sql = postgres(options); expect( ( await sql.begin(sql => [ @@ -636,12 +681,21 @@ if (isDockerEnabled()) { ).toBe("testing"); }); - test("Uncaught transaction request errosó rs bubbles to transaction", async () => { - const sql = postgres({ ...options, debug: true, idle_timeout: 1, fetch_types: false }); + test("Idle timeout retry works", async () => { + await using sql = postgres({ ...options, idleTimeout: 1 }); + await sql`select 1`; + await Bun.sleep(1100); // 1.1 seconds so it should retry + await sql`select 1`; + expect().pass(); + }); + + test("Uncaught transaction request errors bubbles to transaction", async () => { + const sql = postgres(options); + process.nextTick(() => sql.close({ timeout: 1 })); expect( await sql .begin(sql => [sql`select wat`, sql`select current_setting('bun_sql.test') as x, ${1} as a`]) - .catch(e => e.errno), + .catch(e => e.errno || e), ).toBe("42703"); }); @@ -993,8 +1047,6 @@ if (isDockerEnabled()) { const sql = postgres(options); const promise = sql`select pg_sleep(0.2) as x`.execute(); - // we await 1 to start the query - await 1; await sql.end(); return expect(await promise).toEqual([{ x: "" }]); }); diff --git a/test/js/sql/tls-sql.test.ts b/test/js/sql/tls-sql.test.ts index bb573a29762832..2272ef0bd1529d 100644 --- a/test/js/sql/tls-sql.test.ts +++ b/test/js/sql/tls-sql.test.ts @@ -152,7 +152,7 @@ if (TLS_POSTGRES_DATABASE_URL) { }); test("Transaction requests are executed implicitly", async () => { - await using sql = new SQL({ ...options, debug: true, idle_timeout: 1, fetch_types: false }); + await using sql = new SQL(options); expect( ( await sql.begin(sql => [ @@ -164,11 +164,11 @@ if (TLS_POSTGRES_DATABASE_URL) { }); test("Uncaught transaction request errors bubbles to transaction", async () => { - await using sql = new SQL({ ...options, debug: true, idle_timeout: 1, fetch_types: false, max: 10 }); + await using sql = new SQL(options); expect( await sql .begin(sql => [sql`select wat`, sql`select current_setting('bun_sql.test') as x, ${1} as a`]) - .catch(e => e.errno), + .catch(e => e.errno || e), ).toBe("42703"); }); @@ -198,9 +198,9 @@ if (TLS_POSTGRES_DATABASE_URL) { }); test("Many transactions at beginning of connection", async () => { - await using sql = new SQL({ ...options, max: 10 }); - const xs = await Promise.all(Array.from({ length: 100 }, () => sql.begin(sql => sql`select 1`))); - return expect(xs.length).toBe(100); + await using sql = new SQL({ ...options, max: 2 }); + const xs = await Promise.all(Array.from({ length: 30 }, () => sql.begin(sql => sql`select 1`))); + return expect(xs.length).toBe(30); }); test("Transactions array", async () => { @@ -212,7 +212,7 @@ if (TLS_POSTGRES_DATABASE_URL) { }); test("Transaction waits", async () => { - await using sql = new SQL({ ...options, max: 10 }); + await using sql = new SQL({ ...options, max: 2 }); await sql`CREATE TEMPORARY TABLE IF NOT EXISTS test (a int)`; await sql.begin(async sql => { await sql`insert into test values(1)`; diff --git a/test/js/third_party/body-parser/bun.lock b/test/js/third_party/body-parser/bun.lock index 41d1c0cae80978..668e84af65c67e 100644 --- a/test/js/third_party/body-parser/bun.lock +++ b/test/js/third_party/body-parser/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "body-parser-test", diff --git a/test/js/third_party/duckdb/duckdb-basic-usage.test.ts b/test/js/third_party/duckdb/duckdb-basic-usage.test.ts new file mode 100644 index 00000000000000..a2c82d5708a0d3 --- /dev/null +++ b/test/js/third_party/duckdb/duckdb-basic-usage.test.ts @@ -0,0 +1,19 @@ +import { libcFamily } from "harness"; +if (libcFamily == "musl") { + // duckdb does not distribute musl binaries, so we skip this test on musl to avoid CI noise + process.exit(0); +} + +import { describe, test, expect } from "bun:test"; +// Must be CJS require so that the above code can exit before we attempt to import DuckDB +const { Database } = require("duckdb"); + +describe("duckdb", () => { + test("basic usage", () => { + const db = new Database(":memory:"); + db.all("SELECT 42 AS fortytwo", (err, res) => { + expect(err).toBeNull(); + expect(res[0].fortytwo).toBe(42); + }); + }); +}); diff --git a/test/js/third_party/esbuild/bun.lock b/test/js/third_party/esbuild/bun.lock index 1c21b7d730a592..a338cedf5d6559 100644 --- a/test/js/third_party/esbuild/bun.lock +++ b/test/js/third_party/esbuild/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { diff --git a/test/js/third_party/prisma/bun.lock b/test/js/third_party/prisma/bun.lock index 8c7aedcbca0ff2..c410521a3b0357 100644 --- a/test/js/third_party/prisma/bun.lock +++ b/test/js/third_party/prisma/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "prisma", @@ -14,6 +14,9 @@ "peerDependencies": { "typescript": "5.0.0", }, + "optionalPeers": [ + "typescript", + ], }, }, "packages": { diff --git a/test/js/third_party/yargs/bun.lock b/test/js/third_party/yargs/bun.lock index af8dc8963d0c6a..578540a8753597 100644 --- a/test/js/third_party/yargs/bun.lock +++ b/test/js/third_party/yargs/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "yargs-test", diff --git a/test/js/web/fetch/fetch.stream.test.ts b/test/js/web/fetch/fetch.stream.test.ts index b3414f453bf96d..40414903c6eb48 100644 --- a/test/js/web/fetch/fetch.stream.test.ts +++ b/test/js/web/fetch/fetch.stream.test.ts @@ -22,58 +22,56 @@ const fixtures = { const invalid = Buffer.from([0xc0]); -const bigText = Buffer.from("a".repeat(1 * 1024 * 1024)); -const smallText = Buffer.from("Hello".repeat(16)); +const bigText = Buffer.alloc(1 * 1024 * 1024, "a"); +const smallText = Buffer.alloc(16 * "Hello".length, "Hello"); const empty = Buffer.alloc(0); describe("fetch() with streaming", () => { [-1, 0, 20, 50, 100].forEach(timeout => { it(`should be able to fail properly when reading from readable stream with timeout ${timeout}`, async () => { - { - using server = Bun.serve({ - port: 0, - async fetch(req) { - return new Response( - new ReadableStream({ - async start(controller) { - controller.enqueue("Hello, World!"); - await Bun.sleep(1000); - controller.enqueue("Hello, World!"); - controller.close(); - }, - }), - { - status: 200, - headers: { - "Content-Type": "text/plain", - }, + using server = Bun.serve({ + port: 0, + async fetch(req) { + return new Response( + new ReadableStream({ + async start(controller) { + controller.enqueue("Hello, World!"); + await Bun.sleep(1000); + controller.enqueue("Hello, World!"); + controller.close(); }, - ); - }, - }); + }), + { + status: 200, + headers: { + "Content-Type": "text/plain", + }, + }, + ); + }, + }); - const server_url = `http://${server.hostname}:${server.port}`; - try { - const res = await fetch(server_url, { - signal: timeout < 0 ? AbortSignal.abort() : AbortSignal.timeout(timeout), - }); + const server_url = `http://${server.hostname}:${server.port}`; + try { + const res = await fetch(server_url, { + signal: timeout < 0 ? AbortSignal.abort() : AbortSignal.timeout(timeout), + }); - const reader = res.body?.getReader(); - let results = []; - while (true) { - const { done, data } = await reader?.read(); - if (data) results.push(data); - if (done) break; - } - expect.unreachable(); - } catch (err: any) { - if (timeout < 0) { - if (err.name !== "AbortError") throw err; - expect(err.message).toBe("The operation was aborted."); - } else { - if (err.name !== "TimeoutError") throw err; - expect(err.message).toBe("The operation timed out."); - } + const reader = res.body?.getReader(); + let results = []; + while (true) { + const { done, data } = await reader?.read(); + if (data) results.push(data); + if (done) break; + } + expect.unreachable(); + } catch (err: any) { + if (timeout < 0) { + if (err.name !== "AbortError") throw err; + expect(err.message).toBe("The operation was aborted."); + } else { + if (err.name !== "TimeoutError") throw err; + expect(err.message).toBe("The operation timed out."); } } }); @@ -665,14 +663,28 @@ describe("fetch() with streaming", () => { switch (compression) { case "gzip-libdeflate": case "gzip": - return Bun.gzipSync(data, { library: compression === "gzip-libdeflate" ? "libdeflate" : "zlib" }); + return Bun.gzipSync(data, { + library: compression === "gzip-libdeflate" ? "libdeflate" : "zlib", + level: 1, // fastest compression + }); case "deflate-libdeflate": case "deflate": - return Bun.deflateSync(data, { library: compression === "deflate-libdeflate" ? "libdeflate" : "zlib" }); + return Bun.deflateSync(data, { + library: compression === "deflate-libdeflate" ? "libdeflate" : "zlib", + level: 1, // fastest compression + }); case "deflate_with_headers": - return zlib.deflateSync(data); + return zlib.deflateSync(data, { + level: 1, // fastest compression + }); case "br": - return zlib.brotliCompressSync(data); + return zlib.brotliCompressSync(data, { + params: { + [zlib.constants.BROTLI_PARAM_QUALITY]: 0, + [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_GENERIC, + [zlib.constants.BROTLI_PARAM_SIZE_HINT]: 0, + }, + }); default: return data; } @@ -682,354 +694,447 @@ describe("fetch() with streaming", () => { const test = skip ? it.skip : it; test(`with invalid utf8 with ${compression} compression`, async () => { - { - const content = Buffer.concat([invalid, Buffer.from("Hello, world!\n".repeat(5), "utf8"), invalid]); - using server = Bun.serve({ - port: 0, - fetch(req) { - return new Response( - new ReadableStream({ - type: "direct", - async pull(controller) { - const data = compress(compression, content); - const size = data.byteLength / 4; - controller.write(data.slice(0, size)); - await controller.flush(); - await Bun.sleep(100); - controller.write(data.slice(size, size * 2)); - await controller.flush(); - await Bun.sleep(100); - controller.write(data.slice(size * 2, size * 3)); - await controller.flush(); - await Bun.sleep(100); - controller.write(data.slice(size * 3, size * 4)); - await controller.flush(); - - controller.close(); - }, - }), - { - status: 200, - headers: { - "Content-Type": "text/plain", - ...headers, - }, + const content = Buffer.concat([invalid, Buffer.from("Hello, world!\n".repeat(5), "utf8"), invalid]); + using server = Bun.serve({ + port: 0, + fetch(req) { + return new Response( + new ReadableStream({ + type: "direct", + async pull(controller) { + const data = compress(compression, content); + const size = data.byteLength / 4; + controller.write(data.slice(0, size)); + await controller.flush(); + await Bun.sleep(100); + controller.write(data.slice(size, size * 2)); + await controller.flush(); + await Bun.sleep(100); + controller.write(data.slice(size * 2, size * 3)); + await controller.flush(); + await Bun.sleep(100); + controller.write(data.slice(size * 3, size * 4)); + await controller.flush(); + + controller.close(); }, - ); - }, - }); + }), + { + status: 200, + headers: { + "Content-Type": "text/plain", + ...headers, + }, + }, + ); + }, + }); - let res = await fetch(`http://${server.hostname}:${server.port}`, {}); - gcTick(false); - const reader = res.body?.getReader(); + let res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const reader = res.body?.getReader(); - let buffer = Buffer.alloc(0); - while (true) { - gcTick(false); + let buffer = Buffer.alloc(0); + while (true) { + gcTick(false); - const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; - if (value) { - buffer = Buffer.concat([buffer, value]); - } - if (done) { - break; - } + const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; + if (value) { + buffer = Buffer.concat([buffer, value]); + } + if (done) { + break; } - - gcTick(false); - expect(buffer).toEqual(content); } + + gcTick(false); + expect(buffer).toEqual(content); }); test(`chunked response works (single chunk) with ${compression} compression`, async () => { - { - const content = "Hello, world!\n".repeat(5); - using server = Bun.serve({ - port: 0, - fetch(req) { - return new Response( - new ReadableStream({ - type: "direct", - async pull(controller) { - const data = compress(compression, Buffer.from(content, "utf8")); - controller.write(data); - await controller.flush(); - controller.close(); - }, - }), - { - status: 200, - headers: { - "Content-Type": "text/plain", - ...headers, - }, + const content = "Hello, world!\n".repeat(5); + using server = Bun.serve({ + port: 0, + fetch(req) { + return new Response( + new ReadableStream({ + type: "direct", + async pull(controller) { + const data = compress(compression, Buffer.from(content, "utf8")); + controller.write(data); + await controller.flush(); + controller.close(); }, - ); - }, - }); - let res = await fetch(`http://${server.hostname}:${server.port}`, {}); - gcTick(false); - const result = await res.text(); - gcTick(false); - expect(result).toBe(content); + }), + { + status: 200, + headers: { + "Content-Type": "text/plain", + ...headers, + }, + }, + ); + }, + }); + let res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const result = await res.text(); + gcTick(false); + expect(result).toBe(content); - res = await fetch(`http://${server.hostname}:${server.port}`, {}); - gcTick(false); - const reader = res.body?.getReader(); + res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const reader = res.body?.getReader(); - let buffer = Buffer.alloc(0); - let parts = 0; - while (true) { - gcTick(false); + let buffer = Buffer.alloc(0); + let parts = 0; + while (true) { + gcTick(false); - const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; - if (value) { - buffer = Buffer.concat([buffer, value]); - parts++; - } - if (done) { - break; - } + const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; + if (value) { + buffer = Buffer.concat([buffer, value]); + parts++; + } + if (done) { + break; } - - gcTick(false); - expect(buffer.toString("utf8")).toBe(content); - expect(parts).toBe(1); } + + gcTick(false); + expect(buffer.toString("utf8")).toBe(content); + expect(parts).toBe(1); }); test(`chunked response works (multiple chunks) with ${compression} compression`, async () => { - { - const content = "Hello, world!\n".repeat(5); - using server = Bun.serve({ - port: 0, - fetch(req) { - return new Response( - new ReadableStream({ - type: "direct", - async pull(controller) { - const data = compress(compression, Buffer.from(content, "utf8")); - const size = data.byteLength / 5; - controller.write(data.slice(0, size)); - await controller.flush(); - await Bun.sleep(100); - controller.write(data.slice(size, size * 2)); - await controller.flush(); - await Bun.sleep(100); - controller.write(data.slice(size * 2, size * 3)); - await controller.flush(); - await Bun.sleep(100); - controller.write(data.slice(size * 3, size * 5)); - await controller.flush(); - - controller.close(); - }, - }), - { - status: 200, - headers: { - "Content-Type": "text/plain", - ...headers, - }, + const content = "Hello, world!\n".repeat(5); + using server = Bun.serve({ + port: 0, + fetch(req) { + return new Response( + new ReadableStream({ + type: "direct", + async pull(controller) { + const data = compress(compression, Buffer.from(content, "utf8")); + const size = data.byteLength / 5; + controller.write(data.slice(0, size)); + await controller.flush(); + await Bun.sleep(100); + controller.write(data.slice(size, size * 2)); + await controller.flush(); + await Bun.sleep(100); + controller.write(data.slice(size * 2, size * 3)); + await controller.flush(); + await Bun.sleep(100); + controller.write(data.slice(size * 3, size * 5)); + await controller.flush(); + + controller.close(); }, - ); - }, - }); - let res = await fetch(`http://${server.hostname}:${server.port}`, {}); - gcTick(false); - const result = await res.text(); - gcTick(false); - expect(result).toBe(content); + }), + { + status: 200, + headers: { + "Content-Type": "text/plain", + ...headers, + }, + }, + ); + }, + }); + let res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const result = await res.text(); + gcTick(false); + expect(result).toBe(content); - res = await fetch(`http://${server.hostname}:${server.port}`, {}); - gcTick(false); - const reader = res.body?.getReader(); + res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const reader = res.body?.getReader(); - let buffer = Buffer.alloc(0); - let parts = 0; - while (true) { - gcTick(false); + let buffer = Buffer.alloc(0); + let parts = 0; + while (true) { + gcTick(false); - const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; - if (value) { - buffer = Buffer.concat([buffer, value]); - } - parts++; - if (done) { - break; - } + const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; + if (value) { + buffer = Buffer.concat([buffer, value]); + } + parts++; + if (done) { + break; } + } + + gcTick(false); + expect(buffer.toString("utf8")).toBe(content); + expect(parts).toBeGreaterThan(1); + }); + test(`Content-Length response works (single part) with ${compression} compression`, async () => { + const content = "a".repeat(1024); + using server = Bun.serve({ + port: 0, + fetch(req) { + return new Response(compress(compression, Buffer.from(content)), { + status: 200, + headers: { + "Content-Type": "text/plain", + ...headers, + }, + }); + }, + }); + let res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const result = await res.text(); + gcTick(false); + expect(result).toBe(content); + + res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const reader = res.body?.getReader(); + + let buffer = Buffer.alloc(0); + let parts = 0; + while (true) { gcTick(false); - expect(buffer.toString("utf8")).toBe(content); - expect(parts).toBeGreaterThan(1); + + const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; + if (value) { + buffer = Buffer.concat([buffer, value]); + parts++; + } + if (done) { + break; + } } + + gcTick(false); + expect(buffer.toString("utf8")).toBe(content); + expect(parts).toBe(1); }); - test(`Content-Length response works (single part) with ${compression} compression`, async () => { - { - const content = "a".repeat(1024); - using server = Bun.serve({ - port: 0, - fetch(req) { - return new Response(compress(compression, Buffer.from(content)), { + test(`Content-Length response works (multiple parts) with ${compression} compression`, async () => { + const rawBytes = Buffer.allocUnsafe(1024 * 1024); + // Random data doesn't compress well. We need enough random data that + // the compressed data is larger than 64 bytes. + require("crypto").randomFillSync(rawBytes); + const content = rawBytes.toString("hex"); + const contentBuffer = Buffer.from(content); + + const data = compress(compression, contentBuffer); + var onReceivedHeaders = Promise.withResolvers(); + using server = Bun.serve({ + port: 0, + async fetch(req) { + return new Response( + new ReadableStream({ + async pull(controller) { + // Ensure we actually send it over the network in multiple chunks. + let tenth = (data.length / 10) | 0; + let remaining = data; + while (remaining.length > 0) { + const chunk = remaining.subarray(0, Math.min(tenth, remaining.length)); + controller.enqueue(chunk); + if (remaining === data) { + await onReceivedHeaders.promise; + } + remaining = remaining.subarray(chunk.length); + await Bun.sleep(1); + } + controller.close(); + }, + }), + { status: 200, headers: { "Content-Type": "text/plain", ...headers, }, - }); - }, - }); - let res = await fetch(`http://${server.hostname}:${server.port}`, {}); - gcTick(false); - const result = await res.text(); - gcTick(false); - expect(result).toBe(content); + }, + ); + }, + }); + let res = await fetch(`http://${server.hostname}:${server.port}`, {}); + let onReceiveHeadersResolve = onReceivedHeaders.resolve; + onReceivedHeaders = Promise.withResolvers(); + onReceiveHeadersResolve(); + gcTick(false); + const result = await res.text(); + gcTick(false); + expect(result).toBe(content); + + res = await fetch(`http://${server.hostname}:${server.port}`, {}); + onReceiveHeadersResolve = onReceivedHeaders.resolve; + onReceivedHeaders = Promise.withResolvers(); + onReceiveHeadersResolve(); - res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const reader = res.body?.getReader(); + + let chunks: Uint8Array[] = []; + let currentRange = 0; + while (true) { gcTick(false); - const reader = res.body?.getReader(); - let buffer = Buffer.alloc(0); - let parts = 0; - while (true) { - gcTick(false); + const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; + if (value) { + chunks.push(value); - const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; - if (value) { - buffer = Buffer.concat([buffer, value]); - parts++; - } - if (done) { - break; - } + // Check the content is what is expected at this time. + // We're avoiding calling .buffer since that changes the internal representation in JSC and we want to test the raw data. + expect(contentBuffer.compare(value, undefined, undefined, currentRange, currentRange + value.length)).toEqual( + 0, + ); + currentRange += value.length; } + if (done) { + break; + } + } - gcTick(false); - expect(buffer.toString("utf8")).toBe(content); - expect(parts).toBe(1); + gcTick(false); + expect(Buffer.concat(chunks).toString("utf8")).toBe(content); + expect(chunks.length).toBeGreaterThan(1); + + currentRange = 0; + for (const chunk of chunks) { + // Check that each chunk hasn't been modified. + // We want to be 100% sure that there is no accidental memory re-use here. + expect(contentBuffer.compare(chunk, undefined, undefined, currentRange, currentRange + chunk.length)).toEqual( + 0, + ); + currentRange += chunk.length; } }); - test(`Content-Length response works (multiple parts) with ${compression} compression`, async () => { - { - const content = "a".repeat(64 * 1024); - var onReceivedHeaders = Promise.withResolvers(); - using server = Bun.serve({ - port: 0, - async fetch(req) { - const data = compress(compression, Buffer.from(content)); - return new Response( - new ReadableStream({ - async pull(controller) { - const firstChunk = data.slice(0, 64); - const secondChunk = data.slice(firstChunk.length); - controller.enqueue(firstChunk); - await onReceivedHeaders.promise; - await Bun.sleep(1); - controller.enqueue(secondChunk); - controller.close(); - }, - }), - { - status: 200, - headers: { - "Content-Type": "text/plain", - ...headers, - }, - }, - ); - }, - }); - let res = await fetch(`http://${server.hostname}:${server.port}`, {}); - onReceivedHeaders.resolve(); - onReceivedHeaders = Promise.withResolvers(); - gcTick(false); - const result = await res.text(); - gcTick(false); - expect(result).toBe(content); + test(`Extra data should be ignored on streaming (multiple chunks, TCP server) with ${compression} compression`, async () => { + const parts = 5; + const content = "Hello".repeat(parts); + using server = Bun.listen({ + port: 0, + hostname: "0.0.0.0", + socket: { + async open(socket) { + var corked: any[] = []; + var cork = true; + async function write(chunk: any) { + await new Promise((resolve, reject) => { + if (cork) { + corked.push(chunk); + } - res = await fetch(`http://${server.hostname}:${server.port}`, {}); - onReceivedHeaders.resolve(); - onReceivedHeaders = Promise.withResolvers(); - gcTick(false); - const reader = res.body?.getReader(); + if (!cork && corked.length) { + socket.write(corked.join("")); + corked.length = 0; + socket.flush(); + } - let buffer = Buffer.alloc(0); - let parts = 0; - while (true) { - gcTick(false); + if (!cork) { + socket.write(chunk); + socket.flush(); + } - const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; - if (value) { - buffer = Buffer.concat([buffer, value]); - parts++; - } - if (done) { - break; - } - } + resolve(); + }); + } + const compressed = compress(compression, Buffer.from(content, "utf8")); + await write("HTTP/1.1 200 OK\r\n"); + await write("Content-Type: text/plain\r\n"); + for (const [key, value] of Object.entries(headers)) { + await write(key + ": " + value + "\r\n"); + } + await write("Content-Length: " + compressed.byteLength + "\r\n"); + await write("\r\n"); + const size = compressed.byteLength / 5; + for (var i = 0; i < 5; i++) { + cork = false; + await write(compressed.slice(size * i, size * (i + 1))); + } + await write("Extra Data!"); + await write("Extra Data!"); + socket.flush(); + }, + drain(socket) {}, + }, + }); + + const res = await fetch(`http://${server.hostname}:${server.port}`, {}); + gcTick(false); + const reader = res.body?.getReader(); + let buffer = Buffer.alloc(0); + while (true) { gcTick(false); - expect(buffer.toString("utf8")).toBe(content); - expect(parts).toBeGreaterThan(1); + + const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; + if (value) { + buffer = Buffer.concat([buffer, value]); + } + if (done) { + break; + } } + + gcTick(false); + expect(buffer.toString("utf8")).toBe(content); }); - test(`Extra data should be ignored on streaming (multiple chunks, TCP server) with ${compression} compression`, async () => { - { - const parts = 5; - const content = "Hello".repeat(parts); - using server = Bun.listen({ - port: 0, - hostname: "0.0.0.0", - socket: { - async open(socket) { - var corked: any[] = []; - var cork = true; - async function write(chunk: any) { - await new Promise((resolve, reject) => { - if (cork) { - corked.push(chunk); - } + test(`Missing data should timeout on streaming (multiple chunks, TCP server) with ${compression} compression`, async () => { + const parts = 5; + const content = "Hello".repeat(parts); + using server = Bun.listen({ + port: 0, + hostname: "0.0.0.0", + socket: { + async open(socket) { + var corked: any[] = []; + var cork = true; + async function write(chunk: any) { + await new Promise((resolve, reject) => { + if (cork) { + corked.push(chunk); + } - if (!cork && corked.length) { - socket.write(corked.join("")); - corked.length = 0; - socket.flush(); - } + if (!cork && corked.length) { + socket.write(corked.join("")); + corked.length = 0; + socket.flush(); + } - if (!cork) { - socket.write(chunk); - socket.flush(); - } + if (!cork) { + socket.write(chunk); + socket.flush(); + } - resolve(); - }); - } - const compressed = compress(compression, Buffer.from(content, "utf8")); - await write("HTTP/1.1 200 OK\r\n"); - await write("Content-Type: text/plain\r\n"); - for (const [key, value] of Object.entries(headers)) { - await write(key + ": " + value + "\r\n"); - } - await write("Content-Length: " + compressed.byteLength + "\r\n"); - await write("\r\n"); - const size = compressed.byteLength / 5; - for (var i = 0; i < 5; i++) { - cork = false; - await write(compressed.slice(size * i, size * (i + 1))); - } - await write("Extra Data!"); - await write("Extra Data!"); - socket.flush(); - }, - drain(socket) {}, + resolve(); + }); + } + const compressed = compress(compression, Buffer.from(content, "utf8")); + await write("HTTP/1.1 200 OK\r\n"); + await write("Content-Type: text/plain\r\n"); + for (const [key, value] of Object.entries(headers)) { + await write(key + ": " + value + "\r\n"); + } + // 10 extra missing bytes that we will never sent + await write("Content-Length: " + compressed.byteLength + 10 + "\r\n"); + await write("\r\n"); + const size = compressed.byteLength / 5; + for (var i = 0; i < 5; i++) { + cork = false; + await write(compressed.slice(size * i, size * (i + 1))); + } + socket.flush(); }, + drain(socket) {}, + }, + }); + try { + const res = await fetch(`http://${server.hostname}:${server.port}`, { + signal: AbortSignal.timeout(1000), }); - - const res = await fetch(`http://${server.hostname}:${server.port}`, {}); gcTick(false); const reader = res.body?.getReader(); @@ -1047,85 +1152,9 @@ describe("fetch() with streaming", () => { } gcTick(false); - expect(buffer.toString("utf8")).toBe(content); - } - }); - - test(`Missing data should timeout on streaming (multiple chunks, TCP server) with ${compression} compression`, async () => { - { - const parts = 5; - const content = "Hello".repeat(parts); - using server = Bun.listen({ - port: 0, - hostname: "0.0.0.0", - socket: { - async open(socket) { - var corked: any[] = []; - var cork = true; - async function write(chunk: any) { - await new Promise((resolve, reject) => { - if (cork) { - corked.push(chunk); - } - - if (!cork && corked.length) { - socket.write(corked.join("")); - corked.length = 0; - socket.flush(); - } - - if (!cork) { - socket.write(chunk); - socket.flush(); - } - - resolve(); - }); - } - const compressed = compress(compression, Buffer.from(content, "utf8")); - await write("HTTP/1.1 200 OK\r\n"); - await write("Content-Type: text/plain\r\n"); - for (const [key, value] of Object.entries(headers)) { - await write(key + ": " + value + "\r\n"); - } - // 10 extra missing bytes that we will never sent - await write("Content-Length: " + compressed.byteLength + 10 + "\r\n"); - await write("\r\n"); - const size = compressed.byteLength / 5; - for (var i = 0; i < 5; i++) { - cork = false; - await write(compressed.slice(size * i, size * (i + 1))); - } - socket.flush(); - }, - drain(socket) {}, - }, - }); - try { - const res = await fetch(`http://${server.hostname}:${server.port}`, { - signal: AbortSignal.timeout(1000), - }); - gcTick(false); - const reader = res.body?.getReader(); - - let buffer = Buffer.alloc(0); - while (true) { - gcTick(false); - - const { done, value } = (await reader?.read()) as ReadableStreamDefaultReadResult; - if (value) { - buffer = Buffer.concat([buffer, value]); - } - if (done) { - break; - } - } - - gcTick(false); - expect(buffer.toString("utf8")).toBe("unreachable"); - } catch (err) { - expect((err as Error).name).toBe("TimeoutError"); - } + expect(buffer.toString("utf8")).toBe("unreachable"); + } catch (err) { + expect((err as Error).name).toBe("TimeoutError"); } }); @@ -1225,93 +1254,91 @@ describe("fetch() with streaming", () => { } test(`can handle socket close with ${compression} compression`, async () => { - { - const parts = 5; - const content = "Hello".repeat(parts); - const { promise, resolve: resolveSocket } = Promise.withResolvers(); - using server = Bun.listen({ - port: 0, - hostname: "0.0.0.0", - socket: { - async open(socket) { - var corked: any[] = []; - var cork = true; - async function write(chunk: any) { - await new Promise((resolve, reject) => { - if (cork) { - corked.push(chunk); - } + const parts = 5; + const content = "Hello".repeat(parts); + const { promise, resolve: resolveSocket } = Promise.withResolvers(); + using server = Bun.listen({ + port: 0, + hostname: "0.0.0.0", + socket: { + async open(socket) { + var corked: any[] = []; + var cork = true; + async function write(chunk: any) { + await new Promise((resolve, reject) => { + if (cork) { + corked.push(chunk); + } - if (!cork && corked.length) { - socket.write(corked.join("")); - corked.length = 0; - socket.flush(); - } + if (!cork && corked.length) { + socket.write(corked.join("")); + corked.length = 0; + socket.flush(); + } - if (!cork) { - socket.write(chunk); - socket.flush(); - } + if (!cork) { + socket.write(chunk); + socket.flush(); + } - resolve(); - }); - } - const compressed = compress(compression, Buffer.from(content, "utf8")); - await write("HTTP/1.1 200 OK\r\n"); - await write("Content-Type: text/plain\r\n"); - for (const [key, value] of Object.entries(headers)) { - await write(key + ": " + value + "\r\n"); - } - // 10 extra missing bytes that we will never sent in this case we will wait to close - await write("Content-Length: " + compressed.byteLength + 10 + "\r\n"); - await write("\r\n"); + resolve(); + }); + } + const compressed = compress(compression, Buffer.from(content, "utf8")); + await write("HTTP/1.1 200 OK\r\n"); + await write("Content-Type: text/plain\r\n"); + for (const [key, value] of Object.entries(headers)) { + await write(key + ": " + value + "\r\n"); + } + // 10 extra missing bytes that we will never sent in this case we will wait to close + await write("Content-Length: " + compressed.byteLength + 10 + "\r\n"); + await write("\r\n"); - resolveSocket(socket); + resolveSocket(socket); - const size = compressed.byteLength / 5; - for (var i = 0; i < 5; i++) { - cork = false; - await write(compressed.slice(size * i, size * (i + 1))); - } - socket.flush(); - }, - drain(socket) {}, + const size = compressed.byteLength / 5; + for (var i = 0; i < 5; i++) { + cork = false; + await write(compressed.slice(size * i, size * (i + 1))); + } + socket.flush(); }, - }); - - let socket: Socket | null = null; + drain(socket) {}, + }, + }); - try { - const res = await fetch(`http://${server.hostname}:${server.port}`, {}); - socket = await promise; - gcTick(false); + let socket: Socket | null = null; - const reader = res.body?.getReader(); + try { + const res = await fetch(`http://${server.hostname}:${server.port}`, {}); + socket = await promise; + gcTick(false); - let buffer = Buffer.alloc(0); + const reader = res.body?.getReader(); - while (true) { - gcTick(false); - const read_promise = reader?.read(); - socket?.end(); - socket = null; - const { done, value } = (await read_promise) as ReadableStreamDefaultReadResult; + let buffer = Buffer.alloc(0); - if (value) { - buffer = Buffer.concat([buffer, value]); - } + while (true) { + gcTick(false); + const read_promise = reader?.read(); + socket?.end(); + socket = null; + const { done, value } = (await read_promise) as ReadableStreamDefaultReadResult; - if (done) { - break; - } + if (value) { + buffer = Buffer.concat([buffer, value]); } - gcTick(false); - expect(buffer.toString("utf8")).toBe("unreachable"); - } catch (err) { - expect((err as Error).name).toBe("Error"); - expect((err as Error).code).toBe("ConnectionClosed"); + if (done) { + break; + } } + + gcTick(false); + expect(buffer.toString("utf8")).toBe("unreachable"); + } catch (err) { + expect((err as Error).name).toBe("Error"); + expect((err as Error).code).toBe("ConnectionClosed"); } }); } diff --git a/test/napi/napi-app/binding.gyp b/test/napi/napi-app/binding.gyp index 39b61162a28755..3c4fa21129efaa 100644 --- a/test/napi/napi-app/binding.gyp +++ b/test/napi/napi-app/binding.gyp @@ -30,5 +30,53 @@ "NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT=1", ], }, + { + "target_name": "nullptr_addon", + "sources": ["null_addon.cpp"], + "include_dirs": [" %s\n", result ? "true" : "false"); + return ok(env); +} + +static napi_value test_is_typedarray(const Napi::CallbackInfo &info) { + bool result; + napi_env env = info.Env(); + NODE_API_CALL(info.Env(), napi_is_typedarray(env, info[1], &result)); + printf("napi_is_typedarray -> %s\n", result ? "true" : "false"); + return ok(env); +} + Napi::Value RunCallback(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); // this function is invoked without the GC callback @@ -1204,6 +1220,9 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports1) { Napi::Function::New(env, create_weird_bigints)); exports.Set("test_extended_error_messages", Napi::Function::New(env, test_extended_error_messages)); + exports.Set("test_is_buffer", Napi::Function::New(env, test_is_buffer)); + exports.Set("test_is_typedarray", + Napi::Function::New(env, test_is_typedarray)); napitests::register_wrap_tests(env, exports); diff --git a/test/napi/napi-app/null_addon.cpp b/test/napi/napi-app/null_addon.cpp new file mode 100644 index 00000000000000..5e02741fa6a742 --- /dev/null +++ b/test/napi/napi-app/null_addon.cpp @@ -0,0 +1,48 @@ +#include +#include + +#define NODE_API_CALL(env, call) \ + do { \ + napi_status status = (call); \ + if (status != napi_ok) { \ + const napi_extended_error_info *error_info = NULL; \ + napi_get_last_error_info((env), &error_info); \ + const char *err_message = error_info->error_message; \ + bool is_pending; \ + napi_is_exception_pending((env), &is_pending); \ + /* If an exception is already pending, don't rethrow it */ \ + if (!is_pending) { \ + const char *message = \ + (err_message == NULL) ? "empty error message" : err_message; \ + napi_throw_error((env), NULL, message); \ + } \ + return NULL; \ + } \ + } while (0) + +/* napi_value */ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) { + napi_value number; + NODE_API_CALL(env, napi_create_int32(env, 123, &number)); + NODE_API_CALL(env, napi_set_named_property(env, exports, "number", number)); + + // These defines are used by binding.gyp to compile three versions of this + // module that return different values +#if defined(MODULE_INIT_RETURN_NULLPTR) + // returning NULL means the exports value should be used as the return value + // of require() + return NULL; +#elif defined(MODULE_INIT_RETURN_NULL) + napi_value null; + NODE_API_CALL(env, napi_get_null(env, &null)); + return null; +#elif defined(MODULE_INIT_RETURN_UNDEFINED) + napi_value undefined; + NODE_API_CALL(env, napi_get_undefined(env, &undefined)); + return undefined; +#elif defined(MODULE_INIT_THROW) + napi_throw_error(env, "CODE_OOPS", "oops!"); + return NULL; +#else +#error Define one of MODULE_INIT_RETURN_{NULLPTR,NULL,UNDEFINED} to determine what to return from NAPI_MODULE_INIT +#endif +} diff --git a/test/napi/napi.test.ts b/test/napi/napi.test.ts index 3068b9c507fe87..d16b7fd9f9e419 100644 --- a/test/napi/napi.test.ts +++ b/test/napi/napi.test.ts @@ -241,7 +241,10 @@ describe("napi", () => { describe("napi_threadsafe_function", () => { it("keeps the event loop alive without async_work", () => { - checkSameOutput("test_promise_with_threadsafe_function", []); + const result = checkSameOutput("test_promise_with_threadsafe_function", []); + expect(result).toContain("tsfn_callback"); + expect(result).toContain("resolved to 1234"); + expect(result).toContain("tsfn_finalize_callback"); }); it("does not hang on finalize", () => { @@ -383,6 +386,38 @@ describe("napi", () => { checkSameOutput("test_extended_error_messages", []); }); }); + + describe.each(["buffer", "typedarray"])("napi_is_%s", kind => { + const tests: Array<[string, boolean]> = [ + ["new Uint8Array()", true], + ["new BigUint64Array()", true], + ["new ArrayBuffer()", false], + ["Buffer.alloc(0)", true], + ["new DataView(new ArrayBuffer())", kind == "buffer"], + ["new (class Foo extends Uint8Array {})()", true], + ["false", false], + ["[1, 2, 3]", false], + ["'hello'", false], + ]; + it("returns consistent values with node.js", () => { + for (const [value, expected] of tests) { + // main.js does eval then spread so to pass a single value we need to wrap in an array + const output = checkSameOutput(`test_is_${kind}`, "[" + value + "]"); + expect(output).toBe(`napi_is_${kind} -> ${expected.toString()}`); + } + }); + }); + + it.each([ + ["nullptr", { number: 123 }], + ["null", null], + ["undefined", undefined], + ])("works when the module register function returns %s", (returnKind, expected) => { + expect(require(`./napi-app/build/Release/${returnKind}_addon.node`)).toEqual(expected); + }); + it("works when the module register function throws", () => { + expect(() => require("./napi-app/build/Release/throw_addon.node")).toThrow(new Error("oops!")); + }); }); function checkSameOutput(test: string, args: any[] | string) { diff --git a/test/package.json b/test/package.json index c957976297aa3e..5ed8350d1546b5 100644 --- a/test/package.json +++ b/test/package.json @@ -28,7 +28,9 @@ "axios": "1.6.8", "body-parser": "1.20.2", "comlink": "4.4.1", + "commander": "12.1.0", "devalue": "5.1.1", + "duckdb": "1.1.3", "es-module-lexer": "1.3.0", "esbuild": "0.18.6", "express": "4.18.2", diff --git a/test/regression/issue/07917/7917.test.ts b/test/regression/issue/07917/7917.test.ts new file mode 100644 index 00000000000000..ba18f7f79d4833 --- /dev/null +++ b/test/regression/issue/07917/7917.test.ts @@ -0,0 +1,19 @@ +test("boundary does not have quotes (#7917)", async () => { + // for `content-type: multipart/form-data; boundary=...` / https://datatracker.ietf.org/doc/html/rfc2046#section-5.1 + // the spec states that the boundary parameter accepts quotes, and both node and bun accept quotes when parsing + // the form data. however, some websites do not accept quotes and node does not quote it. this test ensures that the + // boundary is not quoted. + + const form = new FormData(); + form.append("filename[]", "document.tex"); + form.append("filecontents[]", "\\documentclass{article}\\begin{document}Hello world\\end{document}"); + form.append("return", "pdf"); + const req = new Request("http://localhost:35411", { + method: "POST", + body: form, + }); + const content_type = req.headers.get("content-type"); + const val = await req.text(); + const actual_boundary = val.split("\r")[0].slice(2); + expect(content_type).toEqual(`multipart/form-data; boundary=${actual_boundary}`); +}); diff --git a/test/regression/issue/14982/14982.test.ts b/test/regression/issue/14982/14982.test.ts new file mode 100644 index 00000000000000..c0a683d518b378 --- /dev/null +++ b/test/regression/issue/14982/14982.test.ts @@ -0,0 +1,18 @@ +import { expect, it, describe } from "bun:test"; +import { bunEnv, bunExe } from "../../../harness"; +import { join } from "path"; + +describe("issue 14982", () => { + it("does not hang in commander", async () => { + const process = Bun.spawn([bunExe(), join(__dirname, "commander-hang.fixture.ts"), "test"], { + stdin: "inherit", + stdout: "pipe", + stderr: "inherit", + cwd: __dirname, + env: bunEnv, + }); + await process.exited; + expect(process.exitCode).toBe(0); + expect(await new Response(process.stdout).text()).toBe("Test command\n"); + }, 15000); +}); diff --git a/test/regression/issue/14982/commander-hang.fixture-test.ts b/test/regression/issue/14982/commander-hang.fixture-test.ts new file mode 100644 index 00000000000000..827af4a6629102 --- /dev/null +++ b/test/regression/issue/14982/commander-hang.fixture-test.ts @@ -0,0 +1,8 @@ +import { Command } from "commander"; + +new Command("test") + .action(() => { + console.log("Test command"); + process.exit(0); + }) + .parse(); diff --git a/test/regression/issue/14982/commander-hang.fixture.ts b/test/regression/issue/14982/commander-hang.fixture.ts new file mode 100644 index 00000000000000..c29795dcbe4bcf --- /dev/null +++ b/test/regression/issue/14982/commander-hang.fixture.ts @@ -0,0 +1,4 @@ +import { program } from "commander"; + +// loads ./commander-hang.fixture-test.ts +program.name("test").command("test", "Test command").parse(); diff --git a/test/regression/issue/16702/16702.test.ts b/test/regression/issue/16702/16702.test.ts new file mode 100644 index 00000000000000..5f366c4ebb3b63 --- /dev/null +++ b/test/regression/issue/16702/16702.test.ts @@ -0,0 +1,33 @@ +import { bunExe } from "harness"; + +test("order", async () => { + const res = Bun.spawnSync({ + cmd: [bunExe(), import.meta.dir + "/order-fixture.js"], + stdio: ["pipe", "pipe", "pipe"], + }); + expect({ + stdout: res.stdout.toString().replaceAll("\r", ""), + stderr: res.stderr.toString().replaceAll("\r", ""), + exitCode: res.exitCode, + }).toEqual({ + stdout: "l1\nl2\nl3\n", + stderr: "", + exitCode: 0, + }); +}); + +test("exit", async () => { + const res = Bun.spawnSync({ + cmd: [bunExe(), import.meta.dir + "/exit-fixture.js"], + stdio: ["pipe", "pipe", "pipe"], + }); + expect({ + stdout: res.stdout.toString().replaceAll("\r", ""), + stderr: res.stderr.toString().replaceAll("\r", ""), + exitCode: res.exitCode, + }).toEqual({ + stdout: "l1\nl2\n", + stderr: "", + exitCode: 0, + }); +}); diff --git a/test/regression/issue/16702/exit-fixture.js b/test/regression/issue/16702/exit-fixture.js new file mode 100644 index 00000000000000..0b971657964540 --- /dev/null +++ b/test/regression/issue/16702/exit-fixture.js @@ -0,0 +1,3 @@ +process.stdout.write("l1\n"); +process.stdout.write("l2\n"); +process.exit(0); diff --git a/test/regression/issue/16702/order-fixture.js b/test/regression/issue/16702/order-fixture.js new file mode 100644 index 00000000000000..95572e1189fe5c --- /dev/null +++ b/test/regression/issue/16702/order-fixture.js @@ -0,0 +1,3 @@ +process.stdout.write("l1\n"); +process.stdout.write("l2\n"); +console.log("l3"); diff --git a/test/scripts/bun.lock b/test/scripts/bun.lock index 18d6deadafc998..aeda978fb33cc8 100644 --- a/test/scripts/bun.lock +++ b/test/scripts/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "dependencies": { @@ -114,7 +114,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@7.4.6", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["utf-8-validate"] }, "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="], + "ws": ["ws@7.4.6", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="], "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], diff --git a/test/snippets/bun.lock b/test/snippets/bun.lock index ef9caa0804005a..736cea11120e41 100644 --- a/test/snippets/bun.lock +++ b/test/snippets/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "name": "snippets", diff --git a/test/v8/bad-modules/bun.lock b/test/v8/bad-modules/bun.lock index efe0faa537186e..8d6ae88dc8e563 100644 --- a/test/v8/bad-modules/bun.lock +++ b/test/v8/bad-modules/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "devDependencies": { diff --git a/test/v8/v8-module/bun.lock b/test/v8/v8-module/bun.lock index efe0faa537186e..8d6ae88dc8e563 100644 --- a/test/v8/v8-module/bun.lock +++ b/test/v8/v8-module/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 0, + "lockfileVersion": 1, "workspaces": { "": { "devDependencies": {