diff --git a/.claude/commands/upgrade-webkit.md b/.claude/commands/upgrade-webkit.md index c71308bb7f..0513955763 100644 --- a/.claude/commands/upgrade-webkit.md +++ b/.claude/commands/upgrade-webkit.md @@ -6,8 +6,7 @@ To do that: - git fetch upstream - git merge upstream main - Fix the merge conflicts -- cd ../../ (back to bun) -- make jsc-build (this will take about 7 minutes) +- bun build.ts debug - While it compiles, in another task review the JSC commits between the last version of Webkit and the new version. Write up a summary of the webkit changes in a file called "webkit-changes.md" - bun run build:local (build a build of Bun with the new Webkit, make sure it compiles) - After making sure it compiles, run some code to make sure things work. something like ./build/debug-local/bun-debug --print '42' should be all you need @@ -21,3 +20,7 @@ To do that: - commit + push (without adding the webkit-changes.md file) - create PR titled "Upgrade Webkit to the ", paste your webkit-changes.md into the PR description - delete the webkit-changes.md file + +Things to check for a successful upgrade: +- Did JSType in vendor/WebKit/Source/JavaScriptCore have any recent changes? Does the enum values align with whats present in src/bun.js/bindings/JSType.zig? +- Were there any changes to the webcore code generator? If there are C++ compilation errors, check for differences in some of the generated code in like vendor/WebKit/source/WebCore/bindings/scripts/test/JS/ diff --git a/cmake/targets/BuildBun.cmake b/cmake/targets/BuildBun.cmake index 45d59dca35..b3b38f4850 100644 --- a/cmake/targets/BuildBun.cmake +++ b/cmake/targets/BuildBun.cmake @@ -1310,6 +1310,9 @@ if(WIN32) wsock32 # ws2_32 required by TransmitFile aka sendfile on windows delayimp.lib ) + # Required for static ICU linkage - without this, ICU headers expect DLL linkage + # which causes ABI mismatch and crashes (STATUS_STACK_BUFFER_OVERRUN) + target_compile_definitions(${bun} PRIVATE U_STATIC_IMPLEMENTATION) endif() # --- Packaging --- diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index d2a219e91b..fb895bd2b7 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 1d0216219a3c52cb85195f48f19ba7d5db747ff7) + set(WEBKIT_VERSION c4d4cae03ecef2791f7ad5dd795f722d8be87d41) endif() string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX) @@ -33,8 +33,8 @@ if(WEBKIT_LOCAL) ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders ${WEBKIT_PATH}/bmalloc/Headers ${WEBKIT_PATH}/WTF/Headers - ${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector ${WEBKIT_PATH}/JavaScriptCore/PrivateHeaders/JavaScriptCore + ${WEBKIT_PATH}/JavaScriptCore/DerivedSources/inspector ) endif() diff --git a/src/bun.js/bindings/BunGCOutputConstraint.h b/src/bun.js/bindings/BunGCOutputConstraint.h index b19d4c37a0..6882e1e9d3 100644 --- a/src/bun.js/bindings/BunGCOutputConstraint.h +++ b/src/bun.js/bindings/BunGCOutputConstraint.h @@ -36,7 +36,7 @@ namespace WebCore { class JSHeapData; class DOMGCOutputConstraint : public JSC::MarkingConstraint { - WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMEGCOutputConstraint); + WTF_DEPRECATED_MAKE_FAST_ALLOCATED(DOMGCOutputConstraint); public: DOMGCOutputConstraint(JSC::VM&, JSHeapData&); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 5b40bf30f0..40e401977d 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -730,13 +730,18 @@ JSC::ScriptExecutionStatus Zig::GlobalObject::scriptExecutionStatus(JSC::JSGloba void unsafeEvalNoop(JSGlobalObject*, const WTF::String&) {} +static void queueMicrotaskToEventLoop(JSGlobalObject& globalObject, QueuedTask&& task) +{ + globalObject.vm().queueMicrotask(WTF::move(task)); +} + const JSC::GlobalObjectMethodTable& GlobalObject::globalObjectMethodTable() { static const JSC::GlobalObjectMethodTable table = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, - nullptr, // &queueMicrotaskToEventLoop, // queueTaskToEventLoop + &queueMicrotaskToEventLoop, nullptr, // &shouldInterruptScriptBeforeTimeout, &moduleLoaderImportModule, // moduleLoaderImportModule &moduleLoaderResolve, // moduleLoaderResolve @@ -765,8 +770,7 @@ const JSC::GlobalObjectMethodTable& EvalGlobalObject::globalObjectMethodTable() &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, - // &queueMicrotaskToEventLoop, // queueTaskToEventLoop - nullptr, + &queueMicrotaskToEventLoop, nullptr, // &shouldInterruptScriptBeforeTimeout, &moduleLoaderImportModule, // moduleLoaderImportModule &moduleLoaderResolve, // moduleLoaderResolve @@ -1072,7 +1076,7 @@ JSC_DEFINE_HOST_FUNCTION(functionQueueMicrotask, // BunPerformMicrotaskJob accepts a variable number of arguments (up to: performMicrotask, job, asyncContext, arg0, arg1). // The runtime inspects argumentCount to determine which arguments are present, so callers may pass only the subset they need. // Here we pass: function, callback, asyncContext. - JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, globalObject, function, callback, asyncContext }; + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, 0, globalObject, function, callback, asyncContext }; globalObject->vm().queueMicrotask(WTF::move(task)); return JSC::JSValue::encode(JSC::jsUndefined()); @@ -3103,7 +3107,7 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskCallback(Zig::GlobalObject* g // Do not use JSCell* here because the GC will try to visit it. // Use BunInvokeJobWithArguments to pass the two arguments (ptr and callback) to the trampoline function - JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunInvokeJobWithArguments, globalObject, function, JSValue(std::bit_cast(reinterpret_cast(ptr))), JSValue(std::bit_cast(reinterpret_cast(callback))) }; + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunInvokeJobWithArguments, 0, globalObject, function, JSValue(std::bit_cast(reinterpret_cast(ptr))), JSValue(std::bit_cast(reinterpret_cast(callback))) }; globalObject->vm().queueMicrotask(WTF::move(task)); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 3a4130c983..919505c7c2 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -3540,7 +3540,7 @@ void JSC__JSPromise__rejectOnNextTickWithHandled(JSC::JSPromise* promise, JSC::J value = jsUndefined(); } - JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, globalObject, microtaskFunction, rejectPromiseFunction, globalObject->m_asyncContextData.get()->getInternalField(0), promise, value }; + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, 0, globalObject, microtaskFunction, rejectPromiseFunction, globalObject->m_asyncContextData.get()->getInternalField(0), promise, value }; globalObject->vm().queueMicrotask(WTF::move(task)); RETURN_IF_EXCEPTION(scope, ); } @@ -5428,7 +5428,7 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskJob(JSC::JSGlobalObject* arg0 #endif - JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, globalObject, microTaskFunction, WTF::move(microtaskArgs[0]), WTF::move(microtaskArgs[1]), WTF::move(microtaskArgs[2]), WTF::move(microtaskArgs[3]) }; + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, 0, globalObject, microTaskFunction, WTF::move(microtaskArgs[0]), WTF::move(microtaskArgs[1]), WTF::move(microtaskArgs[2]), WTF::move(microtaskArgs[3]) }; globalObject->vm().queueMicrotask(WTF::move(task)); } diff --git a/src/bun.js/bindings/node/crypto/CryptoSignJob.h b/src/bun.js/bindings/node/crypto/CryptoSignJob.h index f3bf6a5313..a46618cfd7 100644 --- a/src/bun.js/bindings/node/crypto/CryptoSignJob.h +++ b/src/bun.js/bindings/node/crypto/CryptoSignJob.h @@ -11,7 +11,7 @@ JSC_DECLARE_HOST_FUNCTION(jsVerifyOneShot); static const unsigned int NoDsaSignature = static_cast(-1); struct SignJobCtx { - WTF_MAKE_TZONE_ALLOCATED(name); + WTF_MAKE_TZONE_ALLOCATED(SignJobCtx); public: enum class Mode { diff --git a/src/bun.js/bindings/webcore/EventInit.h b/src/bun.js/bindings/webcore/EventInit.h index 1b7fd80941..0efa408e0a 100644 --- a/src/bun.js/bindings/webcore/EventInit.h +++ b/src/bun.js/bindings/webcore/EventInit.h @@ -33,7 +33,7 @@ struct EventInit { bool composed { false }; template void encode(Encoder&) const; - template WARN_UNUSED_RETURN static bool decode(Decoder&, EventInit&); + template [[nodiscard]] static bool decode(Decoder&, EventInit&); }; template diff --git a/src/bun.js/bindings/webcore/HTTPHeaderMap.h b/src/bun.js/bindings/webcore/HTTPHeaderMap.h index 86c67ff4e8..6b834f8451 100644 --- a/src/bun.js/bindings/webcore/HTTPHeaderMap.h +++ b/src/bun.js/bindings/webcore/HTTPHeaderMap.h @@ -261,7 +261,7 @@ public: } template void encode(Encoder &) const; - template WARN_UNUSED_RETURN static bool decode(Decoder &, HTTPHeaderMap &); + template [[nodiscard]] static bool decode(Decoder &, HTTPHeaderMap &); void setUncommonHeader(const String &name, const String &value); void setUncommonHeaderCloneName(const StringView name, const String &value); diff --git a/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp b/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp index 9870e42f39..32e0ede03a 100644 --- a/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp +++ b/src/bun.js/bindings/webcore/PerformanceUserTiming.cpp @@ -43,7 +43,7 @@ namespace WebCore { using NavigationTimingFunction = unsigned long long (PerformanceTiming::*)() const; -static constexpr std::array, 21> restrictedMarkMappings { { +static constexpr SortedArrayMap restrictedMarkFunctions { std::to_array>({ { "connectEnd"_s, &PerformanceTiming::connectEnd }, { "connectStart"_s, &PerformanceTiming::connectStart }, { "domComplete"_s, &PerformanceTiming::domComplete }, @@ -65,8 +65,7 @@ static constexpr std::array JSString* convertEnumerationToJS(JSGlobalObject& lexicalGlobalObject, template<> std::optional parseEnumeration(JSGlobalObject& lexicalGlobalObject, JSValue value) { auto stringValue = value.toWTFString(&lexicalGlobalObject); - static constexpr std::array, 3> mappings { { + static constexpr SortedArrayMap enumerationMapping { std::to_array>({ { "private"_s, CryptoKey::Type::Private }, { "public"_s, CryptoKey::Type::Public }, { "secret"_s, CryptoKey::Type::Secret }, - } }; - static constexpr SortedArrayMap enumerationMapping { mappings }; + }) }; if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); enumerationValue) [[likely]] return *enumerationValue; return std::nullopt; diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp index f27a254b18..6f0819ac7c 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKeyUsage.cpp @@ -64,7 +64,7 @@ template<> JSString* convertEnumerationToJS(JSGlobalObject& lexicalGlobalObject, template<> std::optional parseEnumeration(JSGlobalObject& lexicalGlobalObject, JSValue value) { auto stringValue = value.toWTFString(&lexicalGlobalObject); - static constexpr std::array, 8> mappings { { + static constexpr SortedArrayMap enumerationMapping { std::to_array>({ { "decrypt"_s, CryptoKeyUsage::Decrypt }, { "deriveBits"_s, CryptoKeyUsage::DeriveBits }, { "deriveKey"_s, CryptoKeyUsage::DeriveKey }, @@ -73,8 +73,7 @@ template<> std::optional parseEnumeration(JSGlob { "unwrapKey"_s, CryptoKeyUsage::UnwrapKey }, { "verify"_s, CryptoKeyUsage::Verify }, { "wrapKey"_s, CryptoKeyUsage::WrapKey }, - } }; - static constexpr SortedArrayMap enumerationMapping { mappings }; + }) }; if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); enumerationValue) [[likely]] return *enumerationValue; return std::nullopt; diff --git a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp index bceabcda93..3ebd67bad8 100644 --- a/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp +++ b/src/bun.js/bindings/webcrypto/JSSubtleCrypto.cpp @@ -96,13 +96,12 @@ template<> JSString* convertEnumerationToJS(JSGlobalObject& lexicalGlobalObject, template<> std::optional parseEnumeration(JSGlobalObject& lexicalGlobalObject, JSValue value) { auto stringValue = value.toWTFString(&lexicalGlobalObject); - static constexpr std::array, 4> mappings { { + static constexpr SortedArrayMap enumerationMapping { std::to_array>({ { "jwk"_s, SubtleCrypto::KeyFormat::Jwk }, { "pkcs8"_s, SubtleCrypto::KeyFormat::Pkcs8 }, { "raw"_s, SubtleCrypto::KeyFormat::Raw }, { "spki"_s, SubtleCrypto::KeyFormat::Spki }, - } }; - static constexpr SortedArrayMap enumerationMapping { mappings }; + }) }; if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); enumerationValue) [[likely]] return *enumerationValue; return std::nullopt; diff --git a/src/codegen/bindgen.ts b/src/codegen/bindgen.ts index 386823736f..33bfde7ef1 100644 --- a/src/codegen/bindgen.ts +++ b/src/codegen/bindgen.ts @@ -755,13 +755,12 @@ function emitConvertEnumFunction(w: CodeWriter, type: TypeImpl) { w.line(`template<> std::optional<${name}> parseEnumerationFromString<${name}>(const String& stringValue)`); w.line(`{`); w.line( - ` static constexpr std::array, ${type.data.length}> mappings { {`, + ` static constexpr SortedArrayMap enumerationMapping { std::to_array>({`, ); for (const value of type.data) { w.line(` { ${str(value)}_s, ${name}::${pascal(value)} },`); } - w.line(` } };`); - w.line(` static constexpr SortedArrayMap enumerationMapping { mappings };`); + w.line(` }) };`); w.line(` if (auto* enumerationValue = enumerationMapping.tryGet(stringValue); enumerationValue) [[likely]]`); w.line(` return *enumerationValue;`); w.line(` return std::nullopt;`); diff --git a/src/codegen/bindgenv2/internal/enumeration.ts b/src/codegen/bindgenv2/internal/enumeration.ts index 0e4ec52c53..2839fbeab5 100644 --- a/src/codegen/bindgenv2/internal/enumeration.ts +++ b/src/codegen/bindgenv2/internal/enumeration.ts @@ -143,7 +143,7 @@ export function enumeration( template<> std::optional<${qualifiedName}> WebCore::parseEnumerationFromString<${qualifiedName}>(const WTF::String& stringVal) { - static constexpr ::std::array<${pairType}, ${valueMap.size}> mappings { + static constexpr ::WTF::SortedArrayMap enumerationMapping { ::std::to_array<${pairType}>({ ${joinIndented( 12, Array.from(valueMap.entries()) @@ -155,8 +155,7 @@ export function enumeration( },`; }), )} - }; - static constexpr ::WTF::SortedArrayMap enumerationMapping { mappings }; + }) }; if (auto* enumerationValue = enumerationMapping.tryGet(stringVal)) [[likely]] { return *enumerationValue; } diff --git a/src/codegen/bundle-functions.ts b/src/codegen/bundle-functions.ts index c601fe7118..ae6bcd8a36 100644 --- a/src/codegen/bundle-functions.ts +++ b/src/codegen/bundle-functions.ts @@ -325,7 +325,9 @@ $$capture_start$$(${fn.async ? "async " : ""}${ directives: fn.directives, source: finalReplacement, params: fn.params, - visibility: fn.directives.visibility ?? (fn.directives.linkTimeConstant ? "Private" : "Public"), + // Async functions automatically get Private visibility because the parser + // upgrades them when they use await (see Parser.cpp parseFunctionBody) + visibility: fn.directives.visibility ?? (fn.directives.linkTimeConstant || fn.async ? "Private" : "Public"), isGetter: !!fn.directives.getter, constructAbility: fn.directives.ConstructAbility ?? "CannotConstruct", constructKind: fn.directives.ConstructKind ?? "None",